'use client';

import { useState, useEffect } from 'react';
import { Input } from '@/components/ui';
import { Textarea } from '@/components/ui';
import { Button } from '@/components/ui';
import { Select } from '@/components/ui';
import type { CreateOKRInput, CreateKeyResultInput, TeamMember, KeyResult } from '@/lib/types';
import { PERIOD_SUGGESTIONS } from '@/lib/types';

// Calcule les dates de début et de fin pour un trimestre donné
function getQuarterDates(period: string): { startDate: string; endDate: string } | null {
  // Format attendu: "Q1 2025", "Q2 2026", etc.
  const match = period.match(/^Q(\d)\s+(\d{4})$/);
  if (!match) {
    return null;
  }

  const quarter = parseInt(match[1], 10);
  const year = parseInt(match[2], 10);

  let startMonth = 0; // Janvier = 0
  let endMonth = 2; // Mars = 2
  let endDay = 31;

  switch (quarter) {
    case 1:
      startMonth = 0; // Janvier
      endMonth = 2; // Mars
      endDay = 31;
      break;
    case 2:
      startMonth = 3; // Avril
      endMonth = 5; // Juin
      endDay = 30;
      break;
    case 3:
      startMonth = 6; // Juillet
      endMonth = 8; // Septembre
      endDay = 30;
      break;
    case 4:
      startMonth = 9; // Octobre
      endMonth = 11; // Décembre
      endDay = 31;
      break;
    default:
      return null;
  }

  const startDate = new Date(year, startMonth, 1);
  const endDate = new Date(year, endMonth, endDay);

  return {
    startDate: startDate.toISOString().split('T')[0],
    endDate: endDate.toISOString().split('T')[0],
  };
}

interface KeyResultEditInput extends CreateKeyResultInput {
  id?: string; // If present, it's an existing Key Result to update
}

type KeyResultUpdate = {
  id: string;
  title?: string;
  targetValue?: number;
  unit?: string;
  order?: number;
};

type OKRFormSubmitData =
  | (CreateOKRInput & {
      startDate: Date | string;
      endDate: Date | string;
      keyResultsUpdates?: {
        create?: CreateKeyResultInput[];
        update?: KeyResultUpdate[];
        delete?: string[];
      };
    })
  | CreateOKRInput;

interface OKRFormProps {
  teamMembers: TeamMember[];
  onSubmit: (data: OKRFormSubmitData) => Promise<void>;
  onCancel: () => void;
  initialData?: Partial<CreateOKRInput> & { keyResults?: KeyResult[] };
}

export function OKRForm({ teamMembers, onSubmit, onCancel, initialData }: OKRFormProps) {
  const [teamMemberId, setTeamMemberId] = useState(initialData?.teamMemberId || '');
  const [objective, setObjective] = useState(initialData?.objective || '');
  const [description, setDescription] = useState(initialData?.description || '');
  const [period, setPeriod] = useState(initialData?.period || '');
  const [customPeriod, setCustomPeriod] = useState('');
  const [startDate, setStartDate] = useState(
    initialData?.startDate ? new Date(initialData.startDate).toISOString().split('T')[0] : ''
  );
  const [endDate, setEndDate] = useState(
    initialData?.endDate ? new Date(initialData.endDate).toISOString().split('T')[0] : ''
  );
  // Initialize Key Results from existing ones if in edit mode, otherwise start with one empty
  const [keyResults, setKeyResults] = useState<KeyResultEditInput[]>(() => {
    if (initialData?.keyResults && initialData.keyResults.length > 0) {
      return initialData.keyResults.map((kr): KeyResultEditInput => {
        const result = {
          title: kr.title,
          targetValue: kr.targetValue,
          unit: kr.unit || '%',
          order: kr.order,
        };
        // @ts-expect-error - id is added to extend CreateKeyResultInput to KeyResultEditInput
        result.id = kr.id;
        return result as KeyResultEditInput;
      });
    }
    return [{ title: '', targetValue: 100, unit: '%', order: 0 }];
  });
  const [submitting, setSubmitting] = useState(false);

  // Mise à jour automatique des dates quand la période change
  useEffect(() => {
    if (period && period !== 'custom' && period !== '') {
      const dates = getQuarterDates(period);
      if (dates) {
        setStartDate(dates.startDate);
        setEndDate(dates.endDate);
      }
    }
  }, [period]);

  const addKeyResult = () => {
    if (keyResults.length >= 5) {
      alert('Maximum 5 Key Results autorisés');
      return;
    }
    setKeyResults([
      ...keyResults,
      { title: '', targetValue: 100, unit: '%', order: keyResults.length },
    ]);
  };

  const removeKeyResult = (index: number) => {
    if (keyResults.length <= 1) {
      alert('Au moins un Key Result est requis');
      return;
    }
    setKeyResults(keyResults.filter((_, i) => i !== index).map((kr, i) => ({ ...kr, order: i })));
  };

  const updateKeyResult = (
    index: number,
    field: keyof KeyResultEditInput,
    value: string | number
  ) => {
    const updated = [...keyResults];
    updated[index] = { ...updated[index], [field]: value };
    setKeyResults(updated);
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!teamMemberId || !objective || !period || !startDate || !endDate) {
      alert('Veuillez remplir tous les champs requis');
      return;
    }

    // Validate Key Results
    if (keyResults.some((kr) => !kr.title || kr.targetValue <= 0)) {
      alert('Tous les Key Results doivent avoir un titre et une valeur cible > 0');
      return;
    }

    const finalPeriod = period === 'custom' ? customPeriod : period;
    if (!finalPeriod) {
      alert('Veuillez spécifier une période');
      return;
    }

    setSubmitting(true);
    try {
      // Convert dates to ISO strings for JSON serialization
      const startDateObj = new Date(startDate);
      const endDateObj = new Date(endDate);

      if (isNaN(startDateObj.getTime()) || isNaN(endDateObj.getTime())) {
        alert('Dates invalides');
        setSubmitting(false);
        return;
      }

      const isEditMode = !!initialData?.teamMemberId;

      if (isEditMode) {
        // Type guard for Key Results with id
        type KeyResultWithId = KeyResultEditInput & { id: string };
        const hasId = (kr: KeyResultEditInput): kr is KeyResultWithId => !!kr.id;

        // In edit mode, separate existing Key Results from new ones
        const existingKeyResults: KeyResultWithId[] = keyResults.filter(hasId);
        const originalKeyResults: KeyResult[] = initialData?.keyResults || [];
        const originalIds = new Set(originalKeyResults.map((kr: KeyResult) => kr.id));
        const currentIds = new Set(existingKeyResults.map((kr: KeyResultWithId) => kr.id));

        // Find deleted Key Results
        const deletedIds = Array.from(originalIds).filter((id) => !currentIds.has(id));

        // Find updated Key Results (compare with original)
        const updated = existingKeyResults
          .map((kr: KeyResultWithId) => {
            const original = originalKeyResults.find((okr: KeyResult) => okr.id === kr.id);
            if (!original) return null;

            const changes: {
              id: string;
              title?: string;
              targetValue?: number;
              unit?: string;
              order?: number;
            } = { id: kr.id };
            if (original.title !== kr.title) changes.title = kr.title;
            if (original.targetValue !== kr.targetValue) changes.targetValue = kr.targetValue;
            if (original.unit !== kr.unit) changes.unit = kr.unit;
            if (original.order !== kr.order) changes.order = kr.order;

            return Object.keys(changes).length > 1 ? changes : null; // More than just 'id'
          })
          .filter(
            (
              u
            ): u is {
              id: string;
              title?: string;
              targetValue?: number;
              unit?: string;
              order?: number;
            } => u !== null
          );

        // Update order for all Key Results based on their position
        const allKeyResultsWithOrder = keyResults.map((kr, i) => ({ ...kr, order: i }));
        const existingWithOrder = allKeyResultsWithOrder.filter(hasId) as KeyResultWithId[];
        const newWithOrder = allKeyResultsWithOrder.filter((kr) => !kr.id);

        // Update order for existing Key Results that changed position
        const orderUpdates = existingWithOrder
          .map((kr) => {
            const original = originalKeyResults.find((okr: KeyResult) => okr.id === kr.id);
            if (!original || original.order === kr.order) return null;
            return { id: kr.id, order: kr.order };
          })
          .filter((u): u is { id: string; order: number } => u !== null);

        // Merge order updates with other updates
        const allUpdates = [...updated];
        orderUpdates.forEach((orderUpdate) => {
          const existingUpdate = allUpdates.find((u) => u.id === orderUpdate.id);
          if (existingUpdate) {
            existingUpdate.order = orderUpdate.order;
          } else {
            allUpdates.push(orderUpdate);
          }
        });

        await onSubmit({
          teamMemberId,
          objective,
          description: description || undefined,
          period: finalPeriod,
          startDate: startDateObj.toISOString() as Date | string,
          endDate: endDateObj.toISOString() as Date | string,
          keyResults: [], // Not used in edit mode
          keyResultsUpdates: {
            create:
              newWithOrder.length > 0
                ? newWithOrder.map((kr) => ({
                    title: kr.title,
                    targetValue: kr.targetValue,
                    unit: kr.unit || '%',
                    order: kr.order,
                  }))
                : undefined,
            update: allUpdates.length > 0 ? allUpdates : undefined,
            delete: deletedIds.length > 0 ? deletedIds : undefined,
          },
        } as unknown as OKRFormSubmitData);
      } else {
        // In create mode, just send Key Results normally
        await onSubmit({
          teamMemberId,
          objective,
          description: description || undefined,
          period: finalPeriod,
          startDate: startDateObj,
          endDate: endDateObj,
          keyResults: keyResults.map((kr, i) => ({ ...kr, order: i })),
        });
      }
    } catch (error) {
      console.error('Error submitting OKR:', error);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-6">
      {/* Team Member */}
      <Select
        label="Membre de l'équipe *"
        value={teamMemberId}
        onChange={(e) => setTeamMemberId(e.target.value)}
        options={teamMembers.map((member) => ({
          value: member.id,
          label: member.user.name || member.user.email,
        }))}
        placeholder="Sélectionner un membre"
        required
      />

      {/* Objective */}
      <div>
        <Input
          label="Objective *"
          value={objective}
          onChange={(e) => setObjective(e.target.value)}
          placeholder="Ex: Améliorer la qualité du code"
          required
        />
      </div>

      {/* Description */}
      <div>
        <Textarea
          label="Description"
          value={description}
          onChange={(e) => setDescription(e.target.value)}
          placeholder="Description détaillée de l'objectif..."
          rows={3}
        />
      </div>

      {/* Period */}
      <div>
        <Select
          label="Période *"
          value={period}
          onChange={(e) => setPeriod(e.target.value)}
          options={[
            ...PERIOD_SUGGESTIONS.map((p) => ({
              value: p,
              label: p,
            })),
            {
              value: 'custom',
              label: 'Personnalisée',
            },
          ]}
          placeholder="Sélectionner une période"
          required
        />
        {period === 'custom' && (
          <div className="mt-2">
            <Input
              value={customPeriod}
              onChange={(e) => setCustomPeriod(e.target.value)}
              placeholder="Ex: Q1-Q2 2025"
              required
            />
          </div>
        )}
      </div>

      {/* Dates */}
      <div className="grid grid-cols-2 gap-4">
        <div>
          <Input
            label="Date de début *"
            type="date"
            value={startDate}
            onChange={(e) => setStartDate(e.target.value)}
            required
          />
        </div>
        <div>
          <Input
            label="Date de fin *"
            type="date"
            value={endDate}
            onChange={(e) => setEndDate(e.target.value)}
            required
          />
        </div>
      </div>
      {period && period !== 'custom' && period !== '' && (
        <p className="text-sm text-muted-foreground">
          Les dates sont automatiquement définies selon le trimestre sélectionné. Vous pouvez les
          modifier si nécessaire.
        </p>
      )}

      {/* Key Results */}
      <div>
        <div className="mb-3 flex items-center justify-between">
          <label className="block text-sm font-medium text-foreground">
            Key Results * ({keyResults.length}/5)
          </label>
          <Button
            type="button"
            onClick={addKeyResult}
            variant="outline"
            size="sm"
            disabled={keyResults.length >= 5}
          >
            + Ajouter
          </Button>
        </div>
        <div className="space-y-4">
          {keyResults.map((kr, index) => (
            <div
              key={kr.id || `new-${index}`}
              className="rounded-lg border border-border bg-card p-4"
            >
              <div className="mb-3 flex items-center justify-between">
                <span className="text-sm font-medium text-foreground">Key Result {index + 1}</span>
                {keyResults.length > 1 && (
                  <Button
                    type="button"
                    onClick={() => removeKeyResult(index)}
                    variant="outline"
                    size="sm"
                    style={{
                      color: 'var(--destructive)',
                      borderColor: 'var(--destructive)',
                    }}
                  >
                    Supprimer
                  </Button>
                )}
              </div>
              <div className="space-y-3">
                <Input
                  placeholder="Titre du Key Result"
                  value={kr.title}
                  onChange={(e) => updateKeyResult(index, 'title', e.target.value)}
                  required
                />
                <div className="grid grid-cols-2 gap-3">
                  <Input
                    type="number"
                    placeholder="Valeur cible"
                    value={kr.targetValue}
                    onChange={(e) => updateKeyResult(index, 'targetValue', Number(e.target.value))}
                    min={0}
                    step="0.1"
                    required
                  />
                  <Input
                    placeholder="Unité (%)"
                    value={kr.unit}
                    onChange={(e) => updateKeyResult(index, 'unit', e.target.value)}
                    required
                  />
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>

      {/* Actions */}
      <div className="flex justify-end gap-3">
        <Button type="button" onClick={onCancel} variant="outline">
          Annuler
        </Button>
        <Button
          type="submit"
          disabled={submitting}
          className="bg-[var(--purple)] text-white hover:opacity-90 border-transparent"
        >
          {submitting
            ? initialData?.teamMemberId
              ? 'Modification...'
              : 'Création...'
            : initialData?.teamMemberId
              ? "Modifier l'OKR"
              : "Créer l'OKR"}
        </Button>
      </div>
    </form>
  );
}
