<?php

namespace App\Http\Controllers;

use App\Models\Doctor;
use App\Models\ImportBatch;
use App\Models\MappingDecision;
use App\Models\Mr;
use App\Models\Visit;
use App\Models\VisitRawStaging;
use App\Http\Controllers\DashboardController;
use App\Services\ComplianceScoreService;
use App\Services\VisitMatchingService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class MappingController extends Controller
{
    public function __construct(
        protected VisitMatchingService $matchingService
    ) {}

    public function runMatch(ImportBatch $import)
    {
        $stats = $this->matchingService->runMatchForBatch($import->id);

        return redirect()
            ->route('imports.mapping', $import)
            ->with('success', "Auto-match done. Processed {$stats['processed']} rows, MR resolved: {$stats['mr_resolved']}, with suggestion: {$stats['with_suggestion']}.");
    }

    public function mapping(ImportBatch $import, Request $request)
    {
        $query = VisitRawStaging::where('import_batch_id', $import->id)
            ->with(['resolvedMr', 'suggestedDoctor', 'visit']);

        if ($request->filled('confidence')) {
            if ($request->confidence === 'low') {
                $query->where(function ($q) {
                    $q->whereNull('match_confidence')->orWhere('match_confidence', '<', 70);
                });
            } elseif ($request->confidence === 'high') {
                $query->where('match_confidence', '>=', 70);
            }
        }
        if ($request->filled('mr_id')) {
            $query->where('resolved_mr_id', $request->mr_id);
        }
        if ($request->filled('unmapped')) {
            $query->whereDoesntHave('visit');
        }

        $rows = $query->orderBy('row_index')->paginate(20);
        $mrs = Mr::orderBy('name')->get();
        $doctors = Doctor::with('area')->orderBy('name')->get();

        return view('mapping.index', [
            'batch' => $import,
            'rows' => $rows,
            'mrs' => $mrs,
            'doctors' => $doctors,
        ]);
    }

    public function approve(Request $request)
    {
        $request->validate([
            'staging_row_id' => 'required|exists:visits_raw_staging,id',
            'doctor_id' => 'required_without:new_doctor_name|nullable|exists:doctors,id',
            'new_doctor_name' => 'required_without:doctor_id|nullable|string|max:255',
        ]);

        $row = VisitRawStaging::with('importBatch')->findOrFail($request->staging_row_id);

        if ($row->visit) {
            return back()->with('error', 'This row is already committed.');
        }

        $mrId = $row->resolved_mr_id;
        $visitDate = $row->resolved_visit_date;
        if (! $mrId || ! $visitDate) {
            return back()->with('error', 'MR or visit date could not be resolved. Fix raw data and re-run match.');
        }

        $doctorId = $request->doctor_id;
        if ($request->filled('new_doctor_name')) {
            $doctor = Doctor::create([
                'name' => $request->new_doctor_name,
                'clinic' => $row->raw_data['clinic'] ?? $row->raw_data['location'] ?? null,
            ]);
            $doctorId = $doctor->id;
        }

        DB::transaction(function () use ($row, $mrId, $visitDate, $doctorId, $request) {
            $visit = Visit::create([
                'mr_id' => $mrId,
                'visit_date' => $visitDate,
                'mapped_doctor_id' => $doctorId,
                'confidence_score' => $row->match_confidence,
                'import_batch_id' => $row->import_batch_id,
                'staging_row_id' => $row->id,
            ]);

            MappingDecision::create([
                'visit_id' => $visit->id,
                'staging_row_id' => $row->id,
                'chosen_doctor_id' => $doctorId,
                'decision_by' => auth()->id(),
                'reason_code' => $request->filled('new_doctor_name') ? 'new_doctor' : 'approve',
            ]);
        });

        ComplianceScoreService::invalidateCache();
        DashboardController::invalidateCache();
        return back()->with('success', 'Row approved and visit created.');
    }

    public function markException(Request $request)
    {
        $request->validate([
            'staging_row_id' => 'required|exists:visits_raw_staging,id',
        ]);

        $row = VisitRawStaging::findOrFail($request->staging_row_id);

        if ($row->visit) {
            return back()->with('error', 'This row is already committed.');
        }

        $mrId = $row->resolved_mr_id;
        $visitDate = $row->resolved_visit_date;
        if (! $mrId || ! $visitDate) {
            return back()->with('error', 'MR or visit date could not be resolved.');
        }

        $visit = Visit::create([
            'mr_id' => $mrId,
            'visit_date' => $visitDate,
            'mapped_doctor_id' => null,
            'flags' => ['exception' => true],
            'import_batch_id' => $row->import_batch_id,
            'staging_row_id' => $row->id,
        ]);

        MappingDecision::create([
            'visit_id' => $visit->id,
            'staging_row_id' => $row->id,
            'decision_by' => auth()->id(),
            'reason_code' => 'exception',
        ]);

        ComplianceScoreService::invalidateCache();
        DashboardController::invalidateCache();
        return back()->with('success', 'Row marked as exception.');
    }
}
