<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\ActivityLog;
use App\Models\Incident;
use App\Models\IncidentUpdate;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class IncidentController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $query = Incident::query()->with(['assignee:id,name,avatar', 'subject']);

        if ($s = $request->string('status')->toString()) {
            $query->where('status', $s);
        }
        if ($sev = $request->string('severity')->toString()) {
            $query->where('severity', $sev);
        }
        if ($q = $request->string('q')->toString()) {
            $query->where(function ($w) use ($q) {
                $w->where('title', 'like', "%{$q}%")
                  ->orWhere('public_id', 'like', "%{$q}%");
            });
        }
        // Used by the AI Portal's incremental sync — pull only incidents that
        // changed since the last poll. Filters on updated_at since incidents
        // get touched on status changes / new updates / resolution.
        if ($since = $request->string('updated_after')->toString()) {
            try {
                $query->where('updated_at', '>=', \Carbon\Carbon::parse($since));
            } catch (\Throwable $e) {
                return response()->json(['error' => 'invalid_updated_after', 'message' => 'Could not parse updated_after; expected ISO 8601.'], 422);
            }
        }

        $perPage = min(100, max(10, (int) $request->integer('per_page', 20)));
        $incidents = $query->orderByDesc('detected_at')->paginate($perPage);

        return response()->json([
            'data' => $incidents->items(),
            'meta' => [
                'current_page' => $incidents->currentPage(),
                'last_page' => $incidents->lastPage(),
                'per_page' => $incidents->perPage(),
                'total' => $incidents->total(),
            ],
            'summary' => [
                'total' => Incident::count(),
                'open' => Incident::where('status', 'open')->count(),
                'investigating' => Incident::where('status', 'investigating')->count(),
                'resolved' => Incident::where('status', 'resolved')->count(),
                'mttr_seconds' => (int) Incident::whereNotNull('mttr_seconds')->avg('mttr_seconds'),
            ],
        ]);
    }

    public function show(Incident $incident): JsonResponse
    {
        $incident->load(['assignee', 'creator', 'resolver', 'updates.user', 'subject']);
        return response()->json(['data' => $incident]);
    }

    public function acknowledge(Request $request, Incident $incident): JsonResponse
    {
        abort_unless($request->user()->canAcknowledgeIncidents(), 403);

        if ($incident->status !== 'open') {
            return response()->json(['message' => 'Incident is not open.'], 422);
        }

        $incident->update([
            'status' => 'investigating',
            'acknowledged_at' => now(),
            'assigned_to' => $incident->assigned_to ?? $request->user()->id,
        ]);

        IncidentUpdate::create([
            'incident_id' => $incident->id,
            'user_id' => $request->user()->id,
            'type' => 'acknowledged',
            'message' => $request->input('message'),
        ]);

        ActivityLog::log([
            'action' => 'acknowledged incident',
            'target' => $incident->public_id,
            'subject_type' => Incident::class,
            'subject_id' => $incident->id,
            'category' => 'incident',
            'severity' => 'medium',
        ]);

        return response()->json(['data' => $incident->fresh(['updates.user'])]);
    }

    public function resolve(Request $request, Incident $incident): JsonResponse
    {
        abort_unless($request->user()->canAcknowledgeIncidents(), 403);

        if ($incident->status === 'resolved') {
            return response()->json(['message' => 'Already resolved.'], 422);
        }

        $mttr = $incident->detected_at->diffInSeconds(now());
        $incident->update([
            'status' => 'resolved',
            'resolved_at' => now(),
            'resolved_by' => $request->user()->id,
            'mttr_seconds' => $mttr,
        ]);

        IncidentUpdate::create([
            'incident_id' => $incident->id,
            'user_id' => $request->user()->id,
            'type' => 'resolved',
            'message' => $request->input('message'),
        ]);

        ActivityLog::log([
            'action' => 'resolved incident',
            'target' => $incident->public_id,
            'subject_type' => Incident::class,
            'subject_id' => $incident->id,
            'category' => 'incident',
            'severity' => 'low',
        ]);

        return response()->json(['data' => $incident->fresh(['updates.user'])]);
    }

    public function addUpdate(Request $request, Incident $incident): JsonResponse
    {
        abort_unless($request->user()->canAcknowledgeIncidents(), 403);

        $data = $request->validate([
            'message' => ['required', 'string', 'max:2000'],
            'type' => ['nullable', Rule::in(['update', 'investigating', 'identified'])],
        ]);

        $update = IncidentUpdate::create([
            'incident_id' => $incident->id,
            'user_id' => $request->user()->id,
            'type' => $data['type'] ?? 'update',
            'message' => $data['message'],
        ]);

        return response()->json(['data' => $update->load('user')], 201);
    }

    public function update(Request $request, Incident $incident): JsonResponse
    {
        $data = $request->validate([
            'title' => ['sometimes', 'string', 'max:255'],
            'severity' => ['sometimes', Rule::in(['critical', 'high', 'medium', 'low'])],
            'description' => ['nullable', 'string'],
            'assignee_id' => ['nullable', 'integer', 'exists:users,id'],
        ]);
        $incident->update($data);
        ActivityLog::log(['action' => 'updated incident', 'target' => $incident->title, 'subject_type' => Incident::class, 'subject_id' => $incident->id, 'category' => 'incident', 'severity' => 'low']);
        return response()->json(['data' => $incident->load('assignee', 'subject')]);
    }

    public function destroy(Incident $incident): JsonResponse
    {
        $title = $incident->title;
        $incident->delete();
        ActivityLog::log(['action' => 'deleted incident', 'target' => $title, 'subject_type' => Incident::class, 'subject_id' => null, 'category' => 'incident', 'severity' => 'medium']);
        return response()->json(['ok' => true]);
    }
}
