<?php

namespace Kylin\LawCase\Services;

use Kylin\LawCase\Models\CaseModel;
use Kylin\LawCase\Models\Client;
use Kylin\LawCase\Models\CaseStatusTransition;
use Kylin\LawCase\Enums\CaseStatus;
use Kylin\LawCase\Events\CaseCreated;
use Kylin\LawCase\Events\CaseStatusChanged;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use App\Models\User;

/**
 * 案件服务
 *
 * 律所案件管理核心服务，负责案件的创建、状态流转、
 * 冲突检索、客户关联等业务逻辑。
 */
class CaseService
{
    /** 冲突检索服务 */
    public ConflictCheckService $conflictCheckService;

    public function __construct(ConflictCheckService $conflictCheckService)
    {
        $this->conflictCheckService = $conflictCheckService;
    }

    public function createCase(array $data): CaseModel
    {
        return DB::transaction(function () use ($data) {
            $data['case_no'] = CaseModel::generateCaseNo();
            $data['case_status'] = CaseStatus::CONSULTATION->value;

            $case = CaseModel::create($data);

            Event::dispatch(new CaseCreated($case));

            $this->audit('case_created', $case, ['case_no' => $case->case_no]);

            return $case;
        });
    }

    public function transitionStatus(CaseModel $case, CaseStatus $newStatus, string $reason = ''): CaseModel
    {
        $oldStatus = $case->case_status instanceof CaseStatus
            ? $case->case_status
            : CaseStatus::from($case->case_status);

        if (!$oldStatus->canTransitionTo($newStatus)) {
            throw new \InvalidArgumentException("不允许从 {$oldStatus->label()} 变更为 {$newStatus->label()}");
        }

        // F-CASE-005 关键状态流转需审批：结案/归档需合伙人审批
        $requiresApproval = in_array($newStatus, [CaseStatus::CLOSED, CaseStatus::ARCHIVED]);
        if ($requiresApproval) {
            $user = auth()->user();
            if ($user && !$user->hasRole('super_admin') && !$user->hasRole('partner')) {
                throw new \InvalidArgumentException("{$newStatus->label()}操作需要合伙人或管理员审批");
            }
        }

        return DB::transaction(function () use ($case, $oldStatus, $newStatus, $reason) {
            $case->update(['case_status' => $newStatus->value]);

            // F-CASE-005 状态变更留痕
            CaseStatusTransition::create([
                'case_id' => $case->id,
                'from_status' => $oldStatus->value,
                'to_status' => $newStatus->value,
                'reason' => $reason,
                'approved_by' => auth()->id(),
                'approved_at' => now(),
                'requested_by' => auth()->id(),
            ]);

            Event::dispatch(new CaseStatusChanged($case->fresh(), $oldStatus, $newStatus, $reason));

            $this->audit('case_status_changed', $case, [
                'from' => $oldStatus->value,
                'to' => $newStatus->value,
                'reason' => $reason,
            ]);

            return $case->fresh();
        });
    }

    public function getStatistics(): array
    {
        return [
            'total' => CaseModel::count(),
            'by_status' => CaseModel::selectRaw('case_status, count(*) as count')
                ->groupBy('case_status')
                ->pluck('count', 'case_status')
                ->toArray(),
            'this_month' => CaseModel::whereMonth('created_at', now()->month)->count(),
        ];
    }

    public function updateCase(int $caseId, array $data): CaseModel
    {
        $case = CaseModel::findOrFail($caseId);

        // F-CASE-008 归档保护：归档后只读不可修改
        if ($case->case_status === CaseStatus::ARCHIVED) {
            throw new \InvalidArgumentException('案件已归档，不可修改');
        }

        $case->update($data);

        $this->audit('case_updated', $case, ['case_no' => $case->case_no]);

        return $case->fresh();
    }

    public function deleteCase(int $caseId): bool
    {
        $case = CaseModel::findOrFail($caseId);

        // F-CASE-008 归档保护：归档后不可删除
        if ($case->case_status === CaseStatus::ARCHIVED) {
            throw new \InvalidArgumentException('案件已归档，不可删除');
        }

        $this->audit('case_deleted', $case, ['case_no' => $case->case_no]);

        return $case->delete();
    }

    /**
     * F-CASE-002 智能分案 - 基于律师专业领域、工作量、利益冲突审查结果，智能推荐承办律师
     */
    public function recommendLawyers(string $caseType, ?int $clientId = null): array
    {
        // 1. 获取所有活跃律师（律师+合伙人角色）
        $lawyers = User::where('status', true)
            ->whereHas('role', function ($q) {
                $q->whereIn('name', ['lawyer', 'partner']);
            })
            ->get();

        $recommendations = [];

        foreach ($lawyers as $lawyer) {
            $score = 0;
            $reasons = [];

            // 2. 工作量评分：当前活跃案件越少，得分越高（满分40分）
            $activeCaseCount = CaseModel::where(function ($q) use ($lawyer) {
                $q->where('principal_lawyer_id', $lawyer->id)
                  ->orWhere('assistant_lawyer_id', $lawyer->id);
            })
                ->whereNotIn('case_status', [CaseStatus::CLOSED->value, CaseStatus::ARCHIVED->value])
                ->count();

            $workloadScore = max(0, 40 - ($activeCaseCount * 5));
            $score += $workloadScore;
            $reasons[] = "当前活跃案件{$activeCaseCount}件";

            // 3. 专业领域匹配度（满分30分）：该类型案件办理经验越多，得分越高
            $typeCaseCount = CaseModel::where('case_type', $caseType)
                ->where(function ($q) use ($lawyer) {
                    $q->where('principal_lawyer_id', $lawyer->id)
                      ->orWhere('assistant_lawyer_id', $lawyer->id);
                })
                ->count();

            $expertiseScore = min(30, $typeCaseCount * 10);
            $score += $expertiseScore;
            if ($typeCaseCount > 0) {
                $reasons[] = "同类型案件经验{$typeCaseCount}件";
            }

            // 4. 利益冲突检查（满分30分）：无冲突得满分
            $hasConflict = false;
            if ($clientId) {
                $client = Client::find($clientId);
                if ($client) {
                    $conflictingCases = CaseModel::where('principal_lawyer_id', $lawyer->id)
                        ->where('client_id', '!=', $clientId)
                        ->whereHas('client', function ($q) use ($client) {
                            $q->where('client_name', $client->client_name);
                        })
                        ->exists();

                    if ($conflictingCases) {
                        $hasConflict = true;
                        $reasons[] = "存在利益冲突";
                    }
                }
            }

            $conflictScore = $hasConflict ? 0 : 30;
            $score += $conflictScore;

            $recommendations[] = [
                'lawyer_id' => $lawyer->id,
                'lawyer_name' => $lawyer->name,
                'score' => $score,
                'active_cases' => $activeCaseCount,
                'type_experience' => $typeCaseCount,
                'has_conflict' => $hasConflict,
                'reasons' => $reasons,
            ];
        }

        // 按得分降序排列
        usort($recommendations, fn($a, $b) => $b['score'] <=> $a['score']);

        return $recommendations;
    }

    /**
     * 记录案件审计日志
     *
     * 依据《律师法》和《个人信息保护法》，
     * 案件创建、状态流转、修改、删除等操作需记录审计日志。
     */
    private function audit(string $event, CaseModel $case, array $extra = []): void
    {
        if (! class_exists(\Kylin\AuditLog\Models\AuditLog::class)) {
            return;
        }

        try {
            \Kylin\AuditLog\Models\AuditLog::create([
                'event' => $event,
                'model_type' => CaseModel::class,
                'model_id' => $case->id,
                'new_values' => $extra,
                'old_values' => null,
                'user_id' => auth()->id(),
                'ip' => request()?->ip(),
                'url' => request()?->fullUrl(),
                'tag' => 'law-case',
            ]);
        } catch (\Throwable $e) {
            logger()->warning('案件审计日志写入失败', [
                'error' => $e->getMessage(),
                'case_id' => $case->id,
                'event' => $event,
            ]);
        }
    }
}
