'use client'

import { useState, useEffect, useCallback, useTransition } from 'react'
import { useRouter } from 'next/navigation'
import { useForm, Controller } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { useDebouncedCallback } from 'use-debounce'
import { trpc } from '@/lib/trpc/client'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'
import { Label } from '@/components/ui/label'
import { Textarea } from '@/components/ui/textarea'
import { Slider } from '@/components/ui/slider'
import { Switch } from '@/components/ui/switch'
import { Badge } from '@/components/ui/badge'
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from '@/components/ui/alert-dialog'
import {
  Loader2,
  Save,
  Send,
  CheckCircle2,
  AlertCircle,
  Clock,
  Star,
  ThumbsUp,
  ThumbsDown,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import { toast } from 'sonner'

// Define criterion type from the evaluation form JSON
interface Criterion {
  id: string
  label: string
  description?: string
  scale: number // max value (e.g., 5 or 10)
  weight?: number
  required?: boolean
}

interface EvaluationFormProps {
  assignmentId: string
  evaluationId: string | null
  projectTitle: string
  criteria: Criterion[]
  initialData?: {
    criterionScoresJson: Record<string, number> | null
    globalScore: number | null
    binaryDecision: boolean | null
    feedbackText: string | null
    status: string
  }
  isVotingOpen: boolean
  deadline?: Date | null
}

const createEvaluationSchema = (criteria: Criterion[]) =>
  z.object({
    criterionScores: z.record(z.number()),
    globalScore: z.number().int().min(1).max(10),
    binaryDecision: z.boolean(),
    feedbackText: z.string().min(10, 'Please provide at least 10 characters of feedback'),
  })

type EvaluationFormData = z.infer<ReturnType<typeof createEvaluationSchema>>

export function EvaluationForm({
  assignmentId,
  evaluationId,
  projectTitle,
  criteria,
  initialData,
  isVotingOpen,
  deadline,
}: EvaluationFormProps) {
  const router = useRouter()
  const [isPending, startTransition] = useTransition()
  const [autosaveStatus, setAutosaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle')
  const [lastSaved, setLastSaved] = useState<Date | null>(null)

  // Initialize criterion scores with existing data or defaults
  const defaultCriterionScores: Record<string, number> = {}
  criteria.forEach((c) => {
    defaultCriterionScores[c.id] = initialData?.criterionScoresJson?.[c.id] ?? Math.ceil(c.scale / 2)
  })

  const form = useForm<EvaluationFormData>({
    resolver: zodResolver(createEvaluationSchema(criteria)),
    defaultValues: {
      criterionScores: defaultCriterionScores,
      globalScore: initialData?.globalScore ?? 5,
      binaryDecision: initialData?.binaryDecision ?? false,
      feedbackText: initialData?.feedbackText ?? '',
    },
    mode: 'onChange',
  })

  const { watch, handleSubmit, control, formState } = form
  const { errors, isValid, isDirty } = formState

  // tRPC mutations
  const startEvaluation = trpc.evaluation.start.useMutation()
  const autosave = trpc.evaluation.autosave.useMutation()
  const submit = trpc.evaluation.submit.useMutation()

  const utils = trpc.useUtils()

  // State to track the current evaluation ID (might be created on first autosave)
  const [currentEvaluationId, setCurrentEvaluationId] = useState<string | null>(evaluationId)

  // Create evaluation if it doesn't exist
  useEffect(() => {
    if (!currentEvaluationId && isVotingOpen) {
      startEvaluation.mutate(
        { assignmentId },
        {
          onSuccess: (data) => {
            setCurrentEvaluationId(data.id)
          },
        }
      )
    }
  }, [assignmentId, currentEvaluationId, isVotingOpen])

  // Debounced autosave function
  const debouncedAutosave = useDebouncedCallback(
    async (data: EvaluationFormData) => {
      if (!currentEvaluationId || !isVotingOpen) return

      setAutosaveStatus('saving')

      try {
        await autosave.mutateAsync({
          id: currentEvaluationId,
          criterionScoresJson: data.criterionScores,
          globalScore: data.globalScore,
          binaryDecision: data.binaryDecision,
          feedbackText: data.feedbackText,
        })

        setAutosaveStatus('saved')
        setLastSaved(new Date())

        // Reset to idle after a few seconds
        setTimeout(() => setAutosaveStatus('idle'), 3000)
      } catch (error) {
        console.error('Autosave failed:', error)
        setAutosaveStatus('error')
      }
    },
    3000 // 3 second debounce
  )

  // Watch form values and trigger autosave
  const watchedValues = watch()

  useEffect(() => {
    if (isDirty && isVotingOpen) {
      debouncedAutosave(watchedValues)
    }
  }, [watchedValues, isDirty, isVotingOpen, debouncedAutosave])

  // Submit handler
  const onSubmit = async (data: EvaluationFormData) => {
    if (!currentEvaluationId) return

    try {
      await submit.mutateAsync({
        id: currentEvaluationId,
        criterionScoresJson: data.criterionScores,
        globalScore: data.globalScore,
        binaryDecision: data.binaryDecision,
        feedbackText: data.feedbackText,
      })

      // Invalidate queries and redirect
      utils.assignment.myAssignments.invalidate()

      toast.success('Evaluation submitted successfully!')

      startTransition(() => {
        router.push('/jury/assignments')
        router.refresh()
      })
    } catch (error) {
      console.error('Submit failed:', error)
    }
  }

  const isSubmitted = initialData?.status === 'SUBMITTED' || initialData?.status === 'LOCKED'
  const isReadOnly = isSubmitted || !isVotingOpen

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
      {/* Status bar */}
      <div className="sticky top-0 z-10 -mx-4 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 px-4 py-3 border-b">
        <div className="flex items-center justify-between flex-wrap gap-2">
          <div className="flex items-center gap-3">
            <h2 className="font-semibold truncate max-w-[200px] sm:max-w-none">
              {projectTitle}
            </h2>
            <AutosaveIndicator status={autosaveStatus} lastSaved={lastSaved} />
          </div>

          {!isReadOnly && (
            <div className="flex items-center gap-2">
              <AlertDialog>
                <AlertDialogTrigger asChild>
                  <Button
                    type="button"
                    disabled={!isValid || submit.isPending}
                  >
                    {submit.isPending ? (
                      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    ) : (
                      <Send className="mr-2 h-4 w-4" />
                    )}
                    Submit Evaluation
                  </Button>
                </AlertDialogTrigger>
                <AlertDialogContent>
                  <AlertDialogHeader>
                    <AlertDialogTitle>Submit Evaluation?</AlertDialogTitle>
                    <AlertDialogDescription>
                      Once submitted, you cannot edit your evaluation. Please review
                      your scores and feedback before confirming.
                    </AlertDialogDescription>
                  </AlertDialogHeader>
                  <AlertDialogFooter>
                    <AlertDialogCancel>Cancel</AlertDialogCancel>
                    <AlertDialogAction
                      onClick={handleSubmit(onSubmit)}
                      disabled={submit.isPending}
                    >
                      {submit.isPending ? (
                        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                      ) : null}
                      Confirm Submit
                    </AlertDialogAction>
                  </AlertDialogFooter>
                </AlertDialogContent>
              </AlertDialog>
            </div>
          )}

          {isReadOnly && (
            <Badge variant="secondary">
              <CheckCircle2 className="mr-1 h-3 w-3" />
              {isSubmitted ? 'Submitted' : 'Read Only'}
            </Badge>
          )}
        </div>
      </div>

      {/* Criteria scoring */}
      {criteria.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle className="text-lg">Evaluation Criteria</CardTitle>
            <CardDescription>
              Rate the project on each criterion below
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-6">
            {criteria.map((criterion) => (
              <CriterionField
                key={criterion.id}
                criterion={criterion}
                control={control}
                disabled={isReadOnly}
              />
            ))}
          </CardContent>
        </Card>
      )}

      {/* Global score */}
      <Card>
        <CardHeader>
          <CardTitle className="text-lg">Overall Score</CardTitle>
          <CardDescription>
            Rate the project overall on a scale of 1 to 10
          </CardDescription>
        </CardHeader>
        <CardContent>
          <Controller
            name="globalScore"
            control={control}
            render={({ field }) => (
              <div className="space-y-4">
                <div className="flex items-center justify-between">
                  <span className="text-sm text-muted-foreground">Poor</span>
                  <span className="text-4xl font-bold">{field.value}</span>
                  <span className="text-sm text-muted-foreground">Excellent</span>
                </div>
                <Slider
                  min={1}
                  max={10}
                  step={1}
                  value={[field.value]}
                  onValueChange={(v) => field.onChange(v[0])}
                  disabled={isReadOnly}
                  className="py-4"
                />
                <div className="flex justify-between">
                  {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((num) => (
                    <button
                      key={num}
                      type="button"
                      onClick={() => !isReadOnly && field.onChange(num)}
                      disabled={isReadOnly}
                      className={cn(
                        'w-8 h-8 rounded-full text-sm font-medium transition-colors',
                        field.value === num
                          ? 'bg-primary text-primary-foreground'
                          : 'bg-muted hover:bg-muted/80',
                        isReadOnly && 'opacity-50 cursor-not-allowed'
                      )}
                    >
                      {num}
                    </button>
                  ))}
                </div>
              </div>
            )}
          />
        </CardContent>
      </Card>

      {/* Binary decision */}
      <Card>
        <CardHeader>
          <CardTitle className="text-lg">Recommendation</CardTitle>
          <CardDescription>
            Do you recommend this project to advance to the next round?
          </CardDescription>
        </CardHeader>
        <CardContent>
          <Controller
            name="binaryDecision"
            control={control}
            render={({ field }) => (
              <div className="flex gap-4">
                <Button
                  type="button"
                  variant={field.value ? 'default' : 'outline'}
                  className={cn(
                    'flex-1 h-20',
                    field.value && 'bg-green-600 hover:bg-green-700'
                  )}
                  onClick={() => !isReadOnly && field.onChange(true)}
                  disabled={isReadOnly}
                >
                  <ThumbsUp className="mr-2 h-6 w-6" />
                  Yes, Recommend
                </Button>
                <Button
                  type="button"
                  variant={!field.value ? 'default' : 'outline'}
                  className={cn(
                    'flex-1 h-20',
                    !field.value && 'bg-red-600 hover:bg-red-700'
                  )}
                  onClick={() => !isReadOnly && field.onChange(false)}
                  disabled={isReadOnly}
                >
                  <ThumbsDown className="mr-2 h-6 w-6" />
                  No, Do Not Recommend
                </Button>
              </div>
            )}
          />
        </CardContent>
      </Card>

      {/* Feedback text */}
      <Card>
        <CardHeader>
          <CardTitle className="text-lg">Written Feedback</CardTitle>
          <CardDescription>
            Provide constructive feedback for this project (minimum 10 characters)
          </CardDescription>
        </CardHeader>
        <CardContent>
          <Controller
            name="feedbackText"
            control={control}
            render={({ field }) => (
              <div className="space-y-2">
                <Textarea
                  {...field}
                  placeholder="Share your thoughts on the project's strengths, weaknesses, and potential..."
                  rows={6}
                  maxLength={5000}
                  disabled={isReadOnly}
                  className={cn(
                    errors.feedbackText && 'border-destructive'
                  )}
                />
                <div className="flex items-center justify-between">
                  {errors.feedbackText ? (
                    <p className="text-sm text-destructive">
                      {errors.feedbackText.message}
                    </p>
                  ) : (
                    <p className="text-sm text-muted-foreground">
                      {field.value.length} characters
                    </p>
                  )}
                </div>
              </div>
            )}
          />
        </CardContent>
      </Card>

      {/* Error display */}
      {submit.error && (
        <Card className="border-destructive">
          <CardContent className="flex items-center gap-2 py-4">
            <AlertCircle className="h-5 w-5 text-destructive" />
            <p className="text-sm text-destructive">
              {submit.error.message || 'Failed to submit evaluation. Please try again.'}
            </p>
          </CardContent>
        </Card>
      )}

      {/* Bottom submit button for mobile */}
      {!isReadOnly && (
        <div className="flex justify-end pb-safe">
          <AlertDialog>
            <AlertDialogTrigger asChild>
              <Button
                type="button"
                size="lg"
                disabled={!isValid || submit.isPending}
                className="w-full sm:w-auto"
              >
                {submit.isPending ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <Send className="mr-2 h-4 w-4" />
                )}
                Submit Evaluation
              </Button>
            </AlertDialogTrigger>
            <AlertDialogContent>
              <AlertDialogHeader>
                <AlertDialogTitle>Submit Evaluation?</AlertDialogTitle>
                <AlertDialogDescription>
                  Once submitted, you cannot edit your evaluation. Please review
                  your scores and feedback before confirming.
                </AlertDialogDescription>
              </AlertDialogHeader>
              <AlertDialogFooter>
                <AlertDialogCancel>Cancel</AlertDialogCancel>
                <AlertDialogAction
                  onClick={handleSubmit(onSubmit)}
                  disabled={submit.isPending}
                >
                  {submit.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : null}
                  Confirm Submit
                </AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>
        </div>
      )}
    </form>
  )
}

// Criterion field component
function CriterionField({
  criterion,
  control,
  disabled,
}: {
  criterion: Criterion
  control: any
  disabled: boolean
}) {
  return (
    <Controller
      name={`criterionScores.${criterion.id}`}
      control={control}
      render={({ field }) => (
        <div className="space-y-3">
          <div className="flex items-start justify-between gap-4">
            <div className="space-y-1">
              <Label className="text-base font-medium">{criterion.label}</Label>
              {criterion.description && (
                <p className="text-sm text-muted-foreground">
                  {criterion.description}
                </p>
              )}
            </div>
            <Badge variant="secondary" className="shrink-0">
              {field.value}/{criterion.scale}
            </Badge>
          </div>

          <div className="flex items-center gap-2">
            <span className="text-xs text-muted-foreground w-4">1</span>
            <Slider
              min={1}
              max={criterion.scale}
              step={1}
              value={[field.value]}
              onValueChange={(v) => field.onChange(v[0])}
              disabled={disabled}
              className="flex-1"
            />
            <span className="text-xs text-muted-foreground w-4">{criterion.scale}</span>
          </div>

          {/* Visual rating buttons */}
          <div className="flex gap-1 flex-wrap">
            {Array.from({ length: criterion.scale }, (_, i) => i + 1).map((num) => (
              <button
                key={num}
                type="button"
                onClick={() => !disabled && field.onChange(num)}
                disabled={disabled}
                className={cn(
                  'w-9 h-9 rounded-md text-sm font-medium transition-colors',
                  field.value === num
                    ? 'bg-primary text-primary-foreground'
                    : field.value > num
                      ? 'bg-primary/20 text-primary'
                      : 'bg-muted hover:bg-muted/80',
                  disabled && 'opacity-50 cursor-not-allowed'
                )}
              >
                {num}
              </button>
            ))}
          </div>
        </div>
      )}
    />
  )
}

// Autosave indicator component
function AutosaveIndicator({
  status,
  lastSaved,
}: {
  status: 'idle' | 'saving' | 'saved' | 'error'
  lastSaved: Date | null
}) {
  if (status === 'idle' && lastSaved) {
    return (
      <span className="text-xs text-muted-foreground hidden sm:inline">
        Saved
      </span>
    )
  }

  if (status === 'saving') {
    return (
      <span className="flex items-center gap-1 text-xs text-muted-foreground">
        <Loader2 className="h-3 w-3 animate-spin" />
        <span className="hidden sm:inline">Saving...</span>
      </span>
    )
  }

  if (status === 'saved') {
    return (
      <span className="flex items-center gap-1 text-xs text-green-600">
        <CheckCircle2 className="h-3 w-3" />
        <span className="hidden sm:inline">Saved</span>
      </span>
    )
  }

  if (status === 'error') {
    return (
      <span className="flex items-center gap-1 text-xs text-destructive">
        <AlertCircle className="h-3 w-3" />
        <span className="hidden sm:inline">Save failed</span>
      </span>
    )
  }

  return null
}
