'use client'

import { useEffect, useState } from 'react'
import { toast } from 'sonner'
import { Loader2 } from 'lucide-react'

import { trpc } from '@/lib/trpc/client'
import { Button } from '@/components/ui/button'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import { Label } from '@/components/ui/label'
import { Textarea } from '@/components/ui/textarea'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'

const REASON_MIN = 10
const REASON_MAX = 2000
const TARGET_ANY = '__any__'

type MentorOption = {
  assignmentId: string
  name: string
}

type RequestChangeDialogProps = {
  projectId: string
  mentors: MentorOption[]
  open: boolean
  onOpenChange: (open: boolean) => void
}

export function RequestChangeDialog({
  projectId,
  mentors,
  open,
  onOpenChange,
}: RequestChangeDialogProps) {
  const [reason, setReason] = useState('')
  const [target, setTarget] = useState<string>(TARGET_ANY)
  const [touched, setTouched] = useState(false)

  const utils = trpc.useUtils()
  const requestChange = trpc.mentor.requestChange.useMutation({
    onSuccess: async () => {
      toast.success(
        "Your request has been sent to the program admins. We'll review it and follow up.",
      )
      onOpenChange(false)
      // Refresh dashboard so the disabled state for the button updates.
      await utils.applicant.getMyDashboard.invalidate()
    },
    onError: (error) => {
      toast.error(error.message || 'Could not send your request. Please try again.')
    },
  })

  // Reset form when the dialog is closed.
  useEffect(() => {
    if (!open) {
      setReason('')
      setTarget(TARGET_ANY)
      setTouched(false)
    }
  }, [open])

  const trimmedReason = reason.trim()
  const reasonTooShort = trimmedReason.length < REASON_MIN
  const reasonTooLong = trimmedReason.length > REASON_MAX
  const reasonInvalid = reasonTooShort || reasonTooLong
  const showReasonError = touched && reasonInvalid

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault()
    setTouched(true)
    if (reasonInvalid) return

    requestChange.mutate({
      projectId,
      targetAssignmentId: target === TARGET_ANY ? undefined : target,
      reason: trimmedReason,
    })
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>Request a mentor change</DialogTitle>
          <DialogDescription>
            Share a few details so the program admins can follow up with you.
            Your current mentor will not see this message.
          </DialogDescription>
        </DialogHeader>
        <form onSubmit={handleSubmit} className="space-y-4">
          {mentors.length > 0 && (
            <div className="space-y-2">
              <Label htmlFor="targetMentor">About a specific mentor</Label>
              <Select value={target} onValueChange={setTarget}>
                <SelectTrigger id="targetMentor">
                  <SelectValue placeholder="Any / general" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={TARGET_ANY}>Any / general</SelectItem>
                  {mentors.map((m) => (
                    <SelectItem key={m.assignmentId} value={m.assignmentId}>
                      {m.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <p className="text-xs text-muted-foreground">
                Optional. Use this if your request is about one of your co-mentors in particular.
              </p>
            </div>
          )}
          <div className="space-y-2">
            <Label htmlFor="reason">
              Why would you like a change?
            </Label>
            <Textarea
              id="reason"
              value={reason}
              onChange={(e) => setReason(e.target.value)}
              onBlur={() => setTouched(true)}
              placeholder="Tell us why you'd like a change. The admin team will follow up."
              rows={6}
              maxLength={REASON_MAX}
              aria-invalid={showReasonError || undefined}
              required
            />
            <div className="flex items-center justify-between text-xs">
              {showReasonError ? (
                <p className="text-destructive">
                  {reasonTooShort
                    ? `Please provide at least ${REASON_MIN} characters.`
                    : `Please keep your message under ${REASON_MAX} characters.`}
                </p>
              ) : (
                <p className="text-muted-foreground">
                  {REASON_MIN}–{REASON_MAX} characters.
                </p>
              )}
              <p className="text-muted-foreground tabular-nums">
                {trimmedReason.length}/{REASON_MAX}
              </p>
            </div>
          </div>
          <DialogFooter>
            <Button
              type="button"
              variant="outline"
              onClick={() => onOpenChange(false)}
              disabled={requestChange.isPending}
            >
              Cancel
            </Button>
            <Button type="submit" disabled={requestChange.isPending}>
              {requestChange.isPending && (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              )}
              Send request
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  )
}
