import { useState, useMemo, useEffect, useRef, useCallback } from "react";
import { useParams, Link } from "wouter";
import { 
  useGetTimesheet, 
  getGetTimesheetQueryKey,
  useUpdateTimesheet,
  useCreateTimesheetLine,
  useDeleteTimesheetLine,
  useUpsertTimeEntries,
  useListProjects,
  getListProjectsQueryKey
} from "@workspace/api-client-react";
import { useQueryClient } from "@tanstack/react-query";
import { 
  ArrowLeft, 
  Save, 
  Send, 
  Plus, 
  Trash2, 
  CheckCircle,
  AlertCircle
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { 
  Select, 
  SelectContent, 
  SelectItem, 
  SelectTrigger, 
  SelectValue 
} from "@/components/ui/select";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { useToast } from "@/hooks/use-toast";
import { formatMonthYear, STATUS_LABELS, STATUS_COLORS, cn } from "@/lib/utils";
import { getDaysInMonth, isWeekend, format } from "date-fns";
import { fr } from "date-fns/locale";

type LocalEntry = {
  timesheetLineId: number;
  date: string;
  hours: number;
};

export default function TimesheetDetailPage() {
  const params = useParams();
  const timesheetId = parseInt(params.id || "0");
  
  const { toast } = useToast();
  const queryClient = useQueryClient();
  
  const { data: timesheet, isLoading } = useGetTimesheet(
    timesheetId,
    { query: { enabled: !!timesheetId, queryKey: getGetTimesheetQueryKey(timesheetId) } }
  );

  const updateTimesheet = useUpdateTimesheet();
  const createLine = useCreateTimesheetLine();
  const deleteLine = useDeleteTimesheetLine();
  const upsertEntries = useUpsertTimeEntries();

  // Local state for optimistic updates
  const [localEntries, setLocalEntries] = useState<Record<string, number>>({});
  const [isAddingLine, setIsAddingLine] = useState(false);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
  
  const { data: projects } = useListProjects({ query: { queryKey: getListProjectsQueryKey() } });

  useEffect(() => {
    if (timesheet?.lines) {
      const initial: Record<string, number> = {};
      timesheet.lines.forEach(line => {
        line.entries?.forEach(entry => {
          const dateStr = typeof entry.date === "string" && entry.date.length > 10
            ? entry.date.slice(0, 10)
            : entry.date;
          initial[`${line.id}-${dateStr}`] = entry.hours;
        });
      });
      setLocalEntries(initial);
      setHasUnsavedChanges(false);
    }
  }, [timesheet]);

  // Derived calendar data
  const { days, daysArray, isEditable } = useMemo(() => {
    if (!timesheet) return { days: 0, daysArray: [], isEditable: false };
    
    const daysCount = getDaysInMonth(new Date(timesheet.year, timesheet.month - 1));
    const arr = Array.from({ length: daysCount }, (_, i) => {
      const date = new Date(timesheet.year, timesheet.month - 1, i + 1);
      return {
        dateStr: format(date, "yyyy-MM-dd"),
        dayNum: i + 1,
        isWeekendDay: isWeekend(date),
        dayName: format(date, "EE", { locale: fr })
      };
    });
    
    return { 
      days: daysCount, 
      daysArray: arr,
      isEditable: timesheet.status === "draft"
    };
  }, [timesheet]);

  const handleCellClick = (lineId: number, dateStr: string) => {
    if (!isEditable) return;
    
    const key = `${lineId}-${dateStr}`;
    const current = localEntries[key] || 0;
    
    // Cycle: 0 -> 0.5 -> 1 -> 0
    let next = 0.5;
    if (current === 0.5) next = 1;
    if (current === 1) next = 0;
    
    setLocalEntries(prev => ({ ...prev, [key]: next }));
    setHasUnsavedChanges(true);
  };

  const mutateFnRef = useRef(upsertEntries.mutate);
  mutateFnRef.current = upsertEntries.mutate;

  const handleSave = useCallback(() => {
    if (!timesheetId) return;
    
    const entriesToSave: LocalEntry[] = [];
    Object.entries(localEntries).forEach(([key, hours]) => {
      const [lineIdStr, date] = key.split("-", 2);
      // Reconstruct the full date string since we split by '-'
      const fullDate = key.substring(lineIdStr.length + 1); 
      
      if (hours > 0) {
        entriesToSave.push({
          timesheetLineId: parseInt(lineIdStr),
          date: fullDate,
          hours
        });
      }
    });

    mutateFnRef.current({
      timesheetId,
      data: { entries: entriesToSave }
    }, {
      onSuccess: () => {
        toast({ title: "Modifications sauvegardées" });
        setHasUnsavedChanges(false);
        queryClient.invalidateQueries({ queryKey: getGetTimesheetQueryKey(timesheetId) });
      },
      onError: () => {
        toast({ title: "Erreur de sauvegarde", variant: "destructive" });
      }
    });
  }, [timesheetId, localEntries, toast, queryClient]);

  const handleSubmit = () => {
    if (hasUnsavedChanges) {
      toast({ title: "Veuillez sauvegarder avant de soumettre", variant: "destructive" });
      return;
    }
    
    if (confirm("Êtes-vous sûr de vouloir soumettre ce CRA ? Il ne pourra plus être modifié.")) {
      updateTimesheet.mutate({
        id: timesheetId,
        data: { status: "submitted" }
      }, {
        onSuccess: () => {
          toast({ title: "CRA soumis avec succès" });
          queryClient.invalidateQueries({ queryKey: getGetTimesheetQueryKey(timesheetId) });
        }
      });
    }
  };

  const handleAddLine = (projectId: number) => {
    createLine.mutate({
      timesheetId,
      data: { projectId }
    }, {
      onSuccess: () => {
        toast({ title: "Ligne ajoutée" });
        setIsAddingLine(false);
        queryClient.invalidateQueries({ queryKey: getGetTimesheetQueryKey(timesheetId) });
      },
      onError: (err: any) => {
        toast({ title: "Erreur", description: err.message, variant: "destructive" });
      }
    });
  };

  const handleDeleteLine = (lineId: number) => {
    if (confirm("Supprimer cette ligne et toutes ses saisies ?")) {
      deleteLine.mutate({
        timesheetId,
        lineId
      }, {
        onSuccess: () => {
          toast({ title: "Ligne supprimée" });
          queryClient.invalidateQueries({ queryKey: getGetTimesheetQueryKey(timesheetId) });
        }
      });
    }
  };

  if (isLoading) {
    return <div className="animate-pulse space-y-6">
      <div className="h-8 w-1/3 bg-muted rounded"></div>
      <div className="h-[400px] bg-muted rounded-xl"></div>
    </div>;
  }

  if (!timesheet) return <div>CRA introuvable</div>;

  // Calculate totals
  const rowTotals: Record<number, number> = {};
  const colTotals: Record<string, number> = {};
  let grandTotal = 0;

  timesheet.lines?.forEach(line => {
    let rowSum = 0;
    daysArray.forEach(({ dateStr }) => {
      const hours = localEntries[`${line.id}-${dateStr}`] || 0;
      rowSum += hours;
      colTotals[dateStr] = (colTotals[dateStr] || 0) + hours;
    });
    rowTotals[line.id] = rowSum;
    grandTotal += rowSum;
  });

  return (
    <div className="space-y-6 flex flex-col h-[calc(100vh-8rem)]">
      <div className="flex items-center justify-between shrink-0">
        <div className="flex items-center gap-4">
          <Link href="/timesheets" className="p-2 rounded-md hover:bg-muted transition-colors">
            <ArrowLeft className="h-5 w-5" />
          </Link>
          <div>
            <div className="flex items-center gap-3">
              <h2 className="text-3xl font-bold tracking-tight capitalize">
                {formatMonthYear(timesheet.year, timesheet.month)}
              </h2>
              <Badge variant="outline" className={cn("font-medium border-none", STATUS_COLORS[timesheet.status])}>
                {STATUS_LABELS[timesheet.status]}
              </Badge>
            </div>
            <p className="text-muted-foreground mt-1">
              Collaborateur: {timesheet.collaborator}
            </p>
          </div>
        </div>

        <div className="flex items-center gap-3">
          {isEditable && (
            <>
              <Button 
                variant={hasUnsavedChanges ? "default" : "outline"} 
                onClick={handleSave}
                disabled={!hasUnsavedChanges || upsertEntries.isPending}
                className="gap-2"
              >
                <Save className="h-4 w-4" />
                {hasUnsavedChanges ? "Sauvegarder les modifs" : "Sauvegardé"}
              </Button>
              <Button 
                variant="default"
                className="gap-2 bg-green-600 hover:bg-green-700 text-white"
                onClick={handleSubmit}
                disabled={hasUnsavedChanges || updateTimesheet.isPending}
              >
                <Send className="h-4 w-4" />
                Soumettre
              </Button>
            </>
          )}
          {timesheet.status === "submitted" && (
            <Badge className="bg-blue-100 text-blue-800 hover:bg-blue-100 border-none px-3 py-1.5 text-sm gap-1">
              <AlertCircle className="h-4 w-4" />
              En attente de validation
            </Badge>
          )}
          {timesheet.status === "validated" && (
            <Badge className="bg-green-100 text-green-800 hover:bg-green-100 border-none px-3 py-1.5 text-sm gap-1">
              <CheckCircle className="h-4 w-4" />
              CRA Validé
            </Badge>
          )}
        </div>
      </div>

      <div className="bg-card rounded-xl border shadow-sm flex-1 min-h-0 flex flex-col overflow-hidden">
        {/* Actions bar */}
        {isEditable && (
          <div className="p-4 border-b flex justify-between items-center bg-muted/20 shrink-0">
            <Button variant="outline" size="sm" onClick={() => setIsAddingLine(true)} className="gap-2">
              <Plus className="h-4 w-4" />
              Ajouter un projet
            </Button>
            <div className="text-sm font-medium">
              Total facturable: <span className="text-lg text-primary">{grandTotal}h</span>
            </div>
          </div>
        )}

        {/* The Grid */}
        <div className="flex-1 overflow-auto relative">
          <table className="w-full text-sm text-left border-collapse min-w-max">
            <thead className="sticky top-0 z-20 bg-muted/80 backdrop-blur supports-[backdrop-filter]:bg-muted/50 text-muted-foreground shadow-sm">
              <tr>
                <th className="sticky left-0 z-30 bg-muted/80 backdrop-blur supports-[backdrop-filter]:bg-muted/50 p-3 font-semibold border-b border-r min-w-[250px] shadow-[2px_0_5px_-2px_rgba(0,0,0,0.1)]">
                  Projet
                </th>
                {daysArray.map(day => (
                  <th 
                    key={day.dateStr} 
                    className={cn(
                      "p-2 font-medium text-center border-b border-r min-w-[40px]",
                      day.isWeekendDay ? "bg-muted/50" : ""
                    )}
                  >
                    <div className="flex flex-col items-center">
                      <span className="text-[10px] uppercase opacity-70">{day.dayName}</span>
                      <span>{day.dayNum}</span>
                    </div>
                  </th>
                ))}
                <th className="p-3 font-semibold border-b text-center sticky right-0 z-20 bg-muted/80 backdrop-blur supports-[backdrop-filter]:bg-muted/50 shadow-[-2px_0_5px_-2px_rgba(0,0,0,0.1)]">
                  Total
                </th>
              </tr>
            </thead>
            <tbody>
              {!timesheet.lines || timesheet.lines.length === 0 ? (
                <tr>
                  <td colSpan={days + 2} className="p-8 text-center text-muted-foreground">
                    Aucun projet ajouté. Cliquez sur "Ajouter un projet" pour commencer.
                  </td>
                </tr>
              ) : (
                timesheet.lines.map(line => (
                  <tr key={line.id} className="border-b hover:bg-muted/20 transition-colors group">
                    <td className="sticky left-0 z-10 bg-card p-3 border-r shadow-[2px_0_5px_-2px_rgba(0,0,0,0.05)] group-hover:bg-muted/20">
                      <div className="flex items-center justify-between">
                        <div className="truncate pr-2">
                          <div className="font-medium truncate" title={line.projectName}>{line.projectName}</div>
                          <div className="text-xs text-muted-foreground">{line.projectCode} {line.client ? `• ${line.client}` : ''}</div>
                        </div>
                        {isEditable && (
                          <Button 
                            variant="ghost" 
                            size="icon" 
                            className="h-6 w-6 opacity-0 group-hover:opacity-100 text-destructive hover:text-destructive hover:bg-destructive/10 shrink-0"
                            onClick={() => handleDeleteLine(line.id)}
                          >
                            <Trash2 className="h-3 w-3" />
                          </Button>
                        )}
                      </div>
                    </td>
                    
                    {daysArray.map(day => {
                      const key = `${line.id}-${day.dateStr}`;
                      const val = localEntries[key] || 0;
                      
                      return (
                        <td 
                          key={day.dateStr}
                          onClick={() => handleCellClick(line.id, day.dateStr)}
                          className={cn(
                            "p-0 text-center border-r transition-colors select-none",
                            day.isWeekendDay ? "bg-muted/30" : "",
                            isEditable ? "cursor-pointer hover:bg-primary/10" : "",
                            val > 0 ? "bg-primary/5 text-primary font-medium" : ""
                          )}
                        >
                          <div className="flex items-center justify-center h-12 w-full">
                            {val === 0 ? <span className="opacity-0 group-hover:opacity-20">-</span> : val}
                          </div>
                        </td>
                      );
                    })}
                    
                    <td className="p-3 text-center font-medium bg-card sticky right-0 z-10 shadow-[-2px_0_5px_-2px_rgba(0,0,0,0.05)] group-hover:bg-muted/20">
                      {rowTotals[line.id] > 0 ? (
                        <Badge variant="secondary" className="bg-primary/10 text-primary hover:bg-primary/20">
                          {rowTotals[line.id]}h
                        </Badge>
                      ) : "-"}
                    </td>
                  </tr>
                ))
              )}
            </tbody>
            <tfoot className="sticky bottom-0 z-20 bg-muted/80 backdrop-blur supports-[backdrop-filter]:bg-muted/50 font-medium shadow-[0_-2px_5px_-2px_rgba(0,0,0,0.1)]">
              <tr>
                <td className="sticky left-0 z-30 p-3 border-r text-right shadow-[2px_0_5px_-2px_rgba(0,0,0,0.1)]">
                  Total du jour
                </td>
                {daysArray.map(day => (
                  <td key={day.dateStr} className="p-2 text-center border-r">
                    {colTotals[day.dateStr] > 0 ? colTotals[day.dateStr] : ""}
                  </td>
                ))}
                <td className="p-3 text-center text-primary text-lg sticky right-0 z-20 shadow-[-2px_0_5px_-2px_rgba(0,0,0,0.1)]">
                  {grandTotal}h
                </td>
              </tr>
            </tfoot>
          </table>
        </div>
      </div>

      <Dialog open={isAddingLine} onOpenChange={setIsAddingLine}>
        <DialogContent className="sm:max-w-[425px]">
          <DialogHeader>
            <DialogTitle>Ajouter un projet</DialogTitle>
          </DialogHeader>
          <div className="py-4">
            <Select onValueChange={(val) => handleAddLine(parseInt(val))}>
              <SelectTrigger>
                <SelectValue placeholder="Sélectionner un projet" />
              </SelectTrigger>
              <SelectContent>
                {projects?.filter(p => p.isActive).map(p => (
                  <SelectItem key={p.id} value={p.id.toString()}>
                    {p.code} - {p.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setIsAddingLine(false)}>
              Annuler
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
