'use client';

import { useState, useEffect, useMemo } from 'react';
import { useParams, useRouter } from 'next/navigation';
import { useQuery } from '@tanstack/react-query';
import { api, ApiError } from '@/lib/api';
import { useMe } from '@/lib/auth';
import { fmtDate, fmtTime } from '@/lib/formatters';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

// ---- Types ----------------------------------------------------------------

interface Allocation {
  allocationId: number;
  userId: number;
  isActive: boolean;
  checkInAt?: string | null;
  checkOutAt?: string | null;
}

interface Vihar {
  viharId: number;
  viharDate: string;
  plannedStartTime: string;
  headSaintName: string;
  departureLocation: { locationId: number; name: string };
  arrivalLocation: { locationId: number; name: string };
  allocations: Allocation[];
}

interface RouteInfo { distanceMeters: number; durationSeconds: number }
interface Coords { lat: number; lng: number; acc: number }

const TOLERANCE_KM = 1.0;

// ---- Helpers --------------------------------------------------------------

function nowHHMM(): string {
  const now = new Date();
  return `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
}

function checkInHHMM(iso: string): string {
  const d = new Date(iso);
  return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
}

function parseDistance(raw: string): number | null {
  const normalized = raw.replace(',', '.');
  const n = parseFloat(normalized);
  return isNaN(n) ? null : n;
}

// ---- Page -----------------------------------------------------------------

export default function CheckOutPage() {
  const { id } = useParams<{ id: string }>();
  const viharId = Number(id);
  const router = useRouter();
  const { data: me } = useMe();

  const { data: vihar, isLoading } = useQuery<Vihar>({
    queryKey: ['vihar', viharId],
    queryFn: () => api.get<Vihar>(`/api/vihars/${viharId}`),
  });

  // Snapshot end time at mount
  const [endTime] = useState(() => nowHHMM());

  // Route suggestion
  const [route, setRoute] = useState<RouteInfo | null>(null);

  const myAlloc = useMemo(
    () => me && vihar ? vihar.allocations.find((a) => a.userId === me.userId && a.isActive) : undefined,
    [me, vihar],
  );

  // Form fields
  const [startTime, setStartTime] = useState('');
  const [distanceRaw, setDistanceRaw] = useState('');
  const [notes, setNotes] = useState('');

  // GPS
  const [gpsState, setGpsState] = useState<'idle' | 'loading' | 'ok' | 'denied'>('idle');
  const [coords, setCoords] = useState<Coords | null>(null);
  const [gpsError, setGpsError] = useState('');
  const [withoutGps, setWithoutGps] = useState(false);

  const [submitting, setSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState('');

  // Set defaults once vihar loads
  useEffect(() => {
    if (!vihar || !myAlloc) return;
    if (myAlloc.checkInAt) {
      setStartTime(checkInHHMM(myAlloc.checkInAt));
    }
  }, [vihar, myAlloc]);

  // Fetch walking route
  useEffect(() => {
    if (!vihar) return;
    const { departureLocation: dep, arrivalLocation: arr } = vihar;
    if (!dep.locationId || !arr.locationId || dep.locationId === arr.locationId) return;
    api.get<RouteInfo>('/api/routes/walking', { query: { from: dep.locationId, to: arr.locationId } })
      .then((r) => {
        setRoute(r);
        setDistanceRaw((prev) => prev || (r.distanceMeters / 1000).toFixed(1));
      })
      .catch(() => {});
  }, [vihar]);

  // GPS auto-start
  useEffect(() => {
    if (!navigator.geolocation) { setGpsState('denied'); setGpsError('Geolocation not supported.'); return; }
    setGpsState('loading');
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        setCoords({ lat: pos.coords.latitude, lng: pos.coords.longitude, acc: pos.coords.accuracy || 0 });
        setGpsState('ok');
      },
      (err) => { setGpsError(err.message || 'Location permission denied.'); setGpsState('denied'); },
      { enableHighAccuracy: true, timeout: 15000, maximumAge: 0 },
    );
  }, []);

  function retryGps() {
    setGpsState('loading'); setGpsError(''); setCoords(null); setWithoutGps(false);
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        setCoords({ lat: pos.coords.latitude, lng: pos.coords.longitude, acc: pos.coords.accuracy || 0 });
        setGpsState('ok');
      },
      (err) => { setGpsError(err.message || 'Permission denied.'); setGpsState('denied'); },
      { enableHighAccuracy: true, timeout: 15000, maximumAge: 0 },
    );
  }

  // Tolerance hint
  const distanceParsed = parseDistance(distanceRaw);
  const suggestedKm = route ? route.distanceMeters / 1000 : null;
  const willAutoAccept = distanceParsed !== null && suggestedKm !== null
    ? Math.abs(distanceParsed - suggestedKm) <= TOLERANCE_KM
    : null;

  async function handleSubmit() {
    if (!myAlloc) { setSubmitError('Your allocation was not found.'); return; }
    if (!startTime) { setSubmitError('Start time is required.'); return; }
    if (!distanceParsed || distanceParsed <= 0) { setSubmitError('Valid distance is required.'); return; }
    if (endTime <= startTime) { setSubmitError('End time must be after start time.'); return; }
    if (gpsState !== 'ok' && !withoutGps) { setSubmitError('Capture your location or continue without GPS.'); return; }

    setSubmitting(true); setSubmitError('');
    try {
      const body: Record<string, unknown> = { startTime, distanceKm: distanceParsed, notes: notes || undefined };
      if (coords && !withoutGps) {
        body.latitude = coords.lat;
        body.longitude = coords.lng;
        if (coords.acc > 0) body.accuracyMeters = Math.round(coords.acc);
      }
      await api.post(`/api/allocations/${myAlloc.allocationId}/check-out`, body);
      router.push(`/volunteer/vihars/${viharId}`);
    } catch (e) {
      setSubmitError(e instanceof ApiError ? e.message : 'Check-out failed');
      setSubmitting(false);
    }
  }

  if (isLoading) return <div className="py-20 text-center text-sm text-ink-300">Loading…</div>;

  return (
    <div className="space-y-5 pb-36">
      <div>
        <h1 className="font-display text-2xl font-semibold text-ink">Check Out</h1>
        <div className="mt-1 h-0.5 w-12 bg-saffron rounded-full" />
      </div>

      {/* Vihar summary */}
      {vihar && (
        <Card className="bg-saffron-50 border-saffron-100">
          <CardContent className="py-3 text-sm">
            <p className="font-medium text-ink">{vihar.headSaintName}</p>
            <p className="text-ink-400">{fmtDate(vihar.viharDate)} · {fmtTime(vihar.plannedStartTime)}</p>
            <p className="text-ink-400">{vihar.departureLocation.name} → {vihar.arrivalLocation.name}</p>
          </CardContent>
        </Card>
      )}

      {/* GPS card */}
      <Card>
        <CardContent className="space-y-3 pt-4">
          <p className="text-sm font-medium text-ink">Your location</p>

          {gpsState === 'loading' && (
            <div className="flex items-center gap-2 text-sm text-saffron-600">
              <svg className="h-4 w-4 animate-spin" viewBox="0 0 24 24" fill="none">
                <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
                <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"/>
              </svg>
              Getting location…
            </div>
          )}

          {gpsState === 'ok' && coords && (
            <div className="flex items-start gap-3">
              <div className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-moss-100 text-moss-600 text-sm">✓</div>
              <div>
                <p className="text-sm font-medium text-moss-700">Location captured</p>
                <p className="text-xs text-ink-300 font-mono">{coords.lat.toFixed(5)}, {coords.lng.toFixed(5)}</p>
                {coords.acc > 0 && <p className="text-xs text-ink-300">Accuracy: ±{Math.round(coords.acc)} m</p>}
              </div>
            </div>
          )}

          {gpsState === 'denied' && (
            <div className="space-y-2">
              <p className="text-sm text-rust">⚠ {gpsError}</p>
              <button onClick={retryGps} className="text-sm text-saffron-600 hover:underline">Try again</button>
              <label className="flex items-center gap-2 cursor-pointer">
                <input
                  type="checkbox"
                  checked={withoutGps}
                  onChange={(e) => setWithoutGps(e.target.checked)}
                  className="h-4 w-4 rounded border-paper-300 accent-saffron"
                />
                <span className="text-sm text-ink-400">Continue without GPS</span>
              </label>
            </div>
          )}
        </CardContent>
      </Card>

      {/* Times */}
      <Card>
        <CardContent className="space-y-4 pt-4">
          <div>
            <Label className="mb-1.5 block text-sm">End time (now)</Label>
            <Input value={endTime} readOnly className="bg-paper-100 text-ink-400" />
          </div>
          <div>
            <Label className="mb-1.5 block text-sm">
              Start time {myAlloc?.checkInAt && <span className="text-xs text-ink-300 font-normal">(from your check-in)</span>}
            </Label>
            <Input
              type="time"
              value={startTime}
              onChange={(e) => setStartTime(e.target.value)}
              placeholder="HH:MM"
            />
          </div>
        </CardContent>
      </Card>

      {/* Distance */}
      <Card>
        <CardContent className="space-y-2 pt-4">
          <Label className="mb-1.5 block text-sm">Distance walked (km)</Label>
          <Input
            type="text"
            inputMode="decimal"
            value={distanceRaw}
            onChange={(e) => setDistanceRaw(e.target.value)}
            placeholder="e.g. 5.2"
            className="text-lg font-medium"
          />
          {suggestedKm !== null && (
            <p className="text-xs text-ink-300">Suggested: {suggestedKm.toFixed(1)} km (Google walking)</p>
          )}
          {distanceParsed !== null && willAutoAccept === true && (
            <div className="flex items-center gap-1.5 text-xs text-moss-600">
              <span>✓</span> <span>Auto-accepted (within ±{TOLERANCE_KM} km)</span>
            </div>
          )}
          {distanceParsed !== null && willAutoAccept === false && (
            <div className="flex items-start gap-1.5 rounded-md bg-amber-50 px-3 py-2 text-xs text-amber-700">
              <span className="mt-0.5">⚠</span>
              <span>This distance differs by more than {TOLERANCE_KM} km from the suggested route. It will need captain approval before the vihar closes.</span>
            </div>
          )}
        </CardContent>
      </Card>

      {/* Notes */}
      <div>
        <Label className="mb-1.5 block text-sm">Notes <span className="text-ink-300">(optional)</span></Label>
        <textarea
          value={notes}
          onChange={(e) => setNotes(e.target.value)}
          rows={3}
          maxLength={500}
          placeholder="Any notes about the walk…"
          className="w-full rounded-md border border-paper-300 bg-white px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-saffron"
        />
      </div>

      {submitError && (
        <p className="rounded-md bg-red-50 px-3 py-2 text-sm text-rust">{submitError}</p>
      )}

      {/* Sticky footer */}
      <div className="fixed bottom-0 left-0 right-0 border-t border-paper-200 bg-paper px-4 py-3 safe-area-inset-bottom">
        <div className="mx-auto flex max-w-lg flex-col gap-2">
          <Button
            className="w-full py-4 text-base"
            onClick={handleSubmit}
            disabled={submitting || !myAlloc}
          >
            {submitting ? 'Submitting…' : 'Complete Vihar'}
          </Button>
          <Button variant="ghost" className="w-full text-sm" onClick={() => router.back()}>
            Cancel
          </Button>
        </div>
      </div>
    </div>
  );
}
