<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Models\Branch;
use App\Services\Care\AdminOverviewService;
use App\Services\Care\CareFeatures;
use App\Services\Care\OrganizationResolver;
use App\Services\Care\PlanService;
use App\Services\Care\ReportService;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ReportController extends Controller
{
    use ScopesToAccount;

    public function __construct(
        protected ReportService $reports,
        protected AdminOverviewService $adminOverview,
    ) {}

    public function index(Request $request): View
    {
        $this->authorizeAbility($request, 'reports.finance.view');
        $organization = $this->organization($request);
        $member = $this->member($request);
        $branchScope = app(OrganizationResolver::class)->branchScope($member);

        $branches = Branch::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->where('is_active', true)
            ->orderBy('name')
            ->get();

        return view('care.admin.analytics', [
            'title' => 'Reports',
            'badge' => 'Analytics · Facility performance',
            'description' => 'Live operational and financial snapshot. Open a detailed report for date ranges and CSV export.',
            'adminOverview' => $this->adminOverview->reportsHub(
                $organization,
                $this->ownerRef($request),
                $branchScope,
            ),
            'catalog' => config('care.report_types'),
            'branches' => $branches,
        ]);
    }

    public function show(Request $request, string $type): View
    {
        $this->authorizeReport($request, $type);
        $organization = $this->organization($request);
        $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request));
        $branchId = $request->input('branch_id') ? (int) $request->input('branch_id') : $branchScope;

        [$from, $to] = $this->dateRange($request);

        $data = $this->reportData($request, $type, $organization->id, $from, $to, $branchId);

        $branches = Branch::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->orderBy('name')
            ->get();

        return view('care.reports.show', [
            'type' => $type,
            'label' => config('care.report_types')[$type] ?? $type,
            'data' => $data,
            'from' => $from->toDateString(),
            'to' => $to->toDateString(),
            'branchId' => $branchId,
            'branches' => $branches,
            'canExport' => app(\App\Services\Care\CarePermissions::class)
                ->can($this->member($request), 'reports.finance.export'),
        ]);
    }

    public function export(Request $request, string $type): StreamedResponse
    {
        $this->authorizeReport($request, $type);
        abort_unless(
            app(\App\Services\Care\CarePermissions::class)->can($this->member($request), 'reports.finance.export'),
            403,
        );

        $organization = $this->organization($request);
        $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request));
        $branchId = $request->input('branch_id') ? (int) $request->input('branch_id') : $branchScope;
        [$from, $to] = $this->dateRange($request);

        $data = $this->reportData($request, $type, $organization->id, $from, $to, $branchId);

        $filename = "care-report-{$type}-".now()->format('Y-m-d').'.csv';

        return response()->streamDownload(function () use ($data, $type) {
            $handle = fopen('php://output', 'w');
            if ($type === 'clinical' && isset($data['diagnoses'])) {
                fputcsv($handle, ['Diagnosis', 'Count']);
                foreach ($data['diagnoses'] as $row) {
                    fputcsv($handle, [$row->description, $row->total]);
                }
            } elseif ($type === 'assessments') {
                fputcsv($handle, ['Section', 'Key', 'Value']);
                foreach ($data['summary'] ?? [] as $key => $value) {
                    fputcsv($handle, ['summary', $key, $value]);
                }
                foreach ($data['by_template'] ?? [] as $row) {
                    fputcsv($handle, ['template', $row->template_code, "{$row->total} total / {$row->completed} completed"]);
                }
                foreach ($data['by_pathway'] ?? [] as $row) {
                    fputcsv($handle, ['pathway', $row->pathway_code, "{$row->total} activations"]);
                }
                foreach ($data['score_averages'] ?? [] as $row) {
                    fputcsv($handle, ['score_avg', $row->template_code, round((float) $row->avg_total, 2)]);
                }
            } else {
                fputcsv($handle, ['Metric', 'Value']);
                foreach ($data as $key => $value) {
                    fputcsv($handle, [$key, is_scalar($value) ? $value : json_encode($value)]);
                }
            }
            fclose($handle);
        }, $filename, ['Content-Type' => 'text/csv']);
    }

    /**
     * @return array<string, mixed>
     */
    protected function reportData(Request $request, string $type, int $organizationId, Carbon $from, Carbon $to, ?int $branchId): array
    {
        return match ($type) {
            'patients' => $this->reports->patientsReport($this->ownerRef($request), $organizationId, $from, $to, $branchId),
            'appointments' => $this->reports->appointmentsReport($this->ownerRef($request), $organizationId, $from, $to, $branchId),
            'laboratory' => $this->reports->laboratoryReport($this->ownerRef($request), $organizationId, $from, $to, $branchId),
            'finance' => $this->reports->financeReport($this->ownerRef($request), $organizationId, $from, $to, $branchId),
            'clinical' => ['diagnoses' => $this->reports->clinicalReport($this->ownerRef($request), $organizationId, $from, $to)],
            'assessments' => $this->reports->assessmentsReport($this->ownerRef($request), $organizationId, $from, $to, $branchId),
            default => abort(404),
        };
    }

    protected function authorizeReport(Request $request, string $type): void
    {
        abort_unless(array_key_exists($type, config('care.report_types')), 404);
        $this->authorizeAbility($request, 'reports.finance.view');

        if ($type === 'assessments') {
            $organization = $this->organization($request);
            abort_unless(
                app(CareFeatures::class)->enabled($organization, CareFeatures::ASSESSMENTS_ENGINE),
                404,
            );
            abort_unless(
                app(PlanService::class)->hasFeature($organization, 'assessment_analytics'),
                403,
                'Assessment analytics require an Enterprise plan.',
            );
        }
    }

    /**
     * @return array{0: Carbon, 1: Carbon}
     */
    protected function dateRange(Request $request): array
    {
        $from = Carbon::parse($request->input('from', now()->subDays(30)->toDateString()))->startOfDay();
        $to = Carbon::parse($request->input('to', now()->toDateString()))->endOfDay();

        return [$from, $to];
    }
}
