<?php

namespace App\Services\DecisionEvents\Handlers;

use App\Models\ArchiveSetting;
use App\Services\Archiving\ArchiveExecutor;
use App\Services\DecisionEvents\Contracts\DecisionEventHandler;
use App\Services\DecisionEvents\DecisionEventContext;

class ArchiveContractHandler implements DecisionEventHandler
{
    /**
     * Config contract:
     * - archive_setting_id: int (required) – which ArchiveSetting to execute
     * - reactivate: bool (optional) – override ArchiveSetting->reactivate per run
     */
    public function handle(DecisionEventContext $context, array $config = []): void
    {
        $activity = $context->activity;

        // Require a contract_id from the activity per request requirements
        $contractId = (int) ($activity->contract_id ?? 0);
        if ($contractId <= 0) {
            throw new \InvalidArgumentException('ArchiveContractHandler requires activity.contract_id');
        }

        $settingId = (int) ($config['archive_setting_id'] ?? 0);
        if ($settingId <= 0) {
            throw new \InvalidArgumentException('ArchiveContractHandler requires config.archive_setting_id');
        }

        $setting = ArchiveSetting::query()->findOrFail($settingId);

        // Optionally override reactivate flag for this run
        if (array_key_exists('reactivate', $config)) {
            $setting->reactivate = (bool) $config['reactivate'];
        }

        // Cancel all active FieldJobs for this contract before archiving (raw update to avoid boot-event side effects)
        \DB::table('field_jobs')
            ->where('contract_id', $contractId)
            ->whereNull('completed_at')
            ->whereNull('cancelled_at')
            ->whereNull('deleted_at')
            ->update(['cancelled_at' => now(), 'updated_at' => now()]);

        $results = app(ArchiveExecutor::class)->executeSetting(
            $setting,
            ['contract_id' => $contractId],
            $activity->user_id ?? null,
            null,
        );

        // If the ArchiveSetting specifies a segment, move the contract to that segment (mirror controller logic)
        if (! empty($setting->segment_id)) {
            try {
                $segmentId = (int) $setting->segment_id;
                $clientCase = $context->clientCase; // expected per context contract
                $contract = $context->contract; // already loaded on context
                if ($clientCase && $contract) {
                    \DB::transaction(function () use ($clientCase, $contract, $segmentId) {
                        // Ensure the segment is attached to the client case (activate if previously inactive)
                        $casePivot = \DB::table('client_case_segment')
                            ->where('client_case_id', $clientCase->id)
                            ->where('segment_id', $segmentId)
                            ->first();
                        if (! $casePivot) {
                            \DB::table('client_case_segment')->insert([
                                'client_case_id' => $clientCase->id,
                                'segment_id' => $segmentId,
                                'active' => true,
                                'created_at' => now(),
                                'updated_at' => now(),
                            ]);
                        } elseif (! $casePivot->active) {
                            \DB::table('client_case_segment')
                                ->where('id', $casePivot->id)
                                ->update(['active' => true, 'updated_at' => now()]);
                        }

                        // Deactivate all current active contract segments
                        \DB::table('contract_segment')
                            ->where('contract_id', $contract->id)
                            ->where('active', true)
                            ->update(['active' => false, 'updated_at' => now()]);

                        // Attach or activate the target segment for this contract
                        $existing = \DB::table('contract_segment')
                            ->where('contract_id', $contract->id)
                            ->where('segment_id', $segmentId)
                            ->first();
                        if ($existing) {
                            \DB::table('contract_segment')
                                ->where('id', $existing->id)
                                ->update(['active' => true, 'updated_at' => now()]);
                        } else {
                            \DB::table('contract_segment')->insert([
                                'contract_id' => $contract->id,
                                'segment_id' => $segmentId,
                                'active' => true,
                                'created_at' => now(),
                                'updated_at' => now(),
                            ]);
                        }
                    });
                }
            } catch (\Throwable $e) {
                // Do not fail the event; log warning for diagnostics
                logger()->warning('ArchiveContractHandler: failed to move contract to segment', [
                    'error' => $e->getMessage(),
                    'setting_id' => $setting->id,
                    'segment_id' => $setting->segment_id,
                    'contract_id' => $contractId,
                ]);
            }
        }
    }
}
