import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Todo, TodoCreateRequest, TodoUpdateRequest } from "@/types";
import { Button } from "@/components/ui/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Calendar } from "@/components/ui/calendar";
import { format } from "date-fns";
import { CalendarIcon, Check, ChevronDown, Loader2, Search, User, Briefcase } from "lucide-react";
import { cn } from "@/lib/utils";
import { Badge } from "@/components/ui/badge";
import { employeeService, projectService } from "@/lib/api";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from "@/components/ui/command";
import { useAuth } from "@/lib/auth-context";

// Custom dropdown component
interface CustomDropdownProps {
  value: string;
  onChange: (value: string) => void;
  options: { value: string; label: string; color?: string }[];
  placeholder: string;
  showBadge?: boolean;
}

function CustomDropdown({ value, onChange, options, placeholder, showBadge = false }: CustomDropdownProps) {
  const [open, setOpen] = useState(false);
  
  const getLabel = () => {
    return options.find(option => option.value === value)?.label || placeholder;
  };
  
  const getColor = () => {
    return options.find(option => option.value === value)?.color || "";
  };
  
  const handleButtonClick = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setOpen(!open);
  };
  
  const handleOptionClick = (optionValue: string) => {
    onChange(optionValue);
    setOpen(false);
  };
  
  return (
    <div className="relative w-full">
      <div
        className={cn(
          "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background cursor-pointer",
          open && "ring-2 ring-ring ring-offset-2"
        )}
        onClick={handleButtonClick}
      >
        {showBadge && value ? (
          <div className="flex items-center gap-2">
            <Badge className={getColor()}>
              {getLabel()}
            </Badge>
          </div>
        ) : (
          <span className={!value ? "text-muted-foreground" : ""}>{getLabel()}</span>
        )}
        <ChevronDown className="h-4 w-4 shrink-0 opacity-50" />
      </div>
      
      {open && (
        <div className="absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md">
          {options.map((option) => (
            <div
              key={option.value}
              className={cn(
                "flex cursor-pointer items-center justify-between rounded-sm px-2 py-1.5 hover:bg-accent hover:text-accent-foreground",
                value === option.value && "bg-accent text-accent-foreground"
              )}
              onClick={() => handleOptionClick(option.value)}
            >
              {showBadge ? (
                <Badge className={option.color}>{option.label}</Badge>
              ) : (
                option.label
              )}
              {value === option.value && <Check className="h-4 w-4" />}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// Custom Employee Dropdown component
interface CustomEmployeeDropdownProps {
  value?: number;
  onChange: (value: number) => void;
  employees: Array<{id: number; firstName: string; lastName: string}>;
  isLoading: boolean;
  placeholder: string;
}

function CustomEmployeeDropdown({ value, onChange, employees, isLoading, placeholder }: CustomEmployeeDropdownProps) {
  const [open, setOpen] = useState(false);
  const [searchTerm, setSearchTerm] = useState("");
  
  const getEmployeeName = (id?: number) => {
    if (!id) return placeholder;
    const employee = employees.find(emp => emp.id === id);
    return employee ? `${employee.firstName} ${employee.lastName}` : `Employee ${id}`;
  };
  
  const getInitials = (firstName: string, lastName: string) => {
    return (firstName.charAt(0) + lastName.charAt(0)).toUpperCase();
  };
  
  const handleButtonClick = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setOpen(!open);
  };
  
  const handleOptionClick = (employeeId: number) => {
    onChange(employeeId);
    setOpen(false);
  };
  
  // Filter employees based on search term
  const filteredEmployees = searchTerm
    ? employees.filter(
        emp => 
          emp.firstName.toLowerCase().includes(searchTerm.toLowerCase()) ||
          emp.lastName.toLowerCase().includes(searchTerm.toLowerCase())
      )
    : employees;
  
  return (
    <div className="relative w-full">
      <div
        className={cn(
          "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background cursor-pointer",
          open && "ring-2 ring-ring ring-offset-2"
        )}
        onClick={handleButtonClick}
      >
        <div className="flex items-center">
          {value && employees.find(e => e.id === value) ? (
            <Avatar className="h-5 w-5 mr-2">
              <AvatarFallback className="text-[10px]">
                {getInitials(
                  employees.find(e => e.id === value)!.firstName,
                  employees.find(e => e.id === value)!.lastName
                )}
              </AvatarFallback>
            </Avatar>
          ) : (
            <User className="h-4 w-4 mr-2 opacity-50" />
          )}
          <span className={!value ? "text-muted-foreground truncate" : "truncate"}>
            {getEmployeeName(value)}
          </span>
        </div>
        <ChevronDown className="h-4 w-4 shrink-0 opacity-50" />
      </div>
      
      {open && (
        <div className="absolute z-50 mt-1 w-full overflow-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md">
          <div className="flex items-center border-b px-3 py-2">
            <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
            <input
              className="flex h-8 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
              placeholder="Search employee..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              onClick={(e) => e.stopPropagation()}
            />
          </div>
          
          <div className="max-h-60 overflow-auto py-1">
            {isLoading ? (
              <div className="flex items-center justify-center p-4">
                <Loader2 className="h-4 w-4 animate-spin" />
                <span className="ml-2">Loading...</span>
              </div>
            ) : filteredEmployees.length === 0 ? (
              <div className="text-center p-2 text-sm text-muted-foreground">
                No employee found
              </div>
            ) : (
              filteredEmployees.map((employee) => (
                <div
                  key={employee.id}
                  className={cn(
                    "flex cursor-pointer items-center px-2 py-1.5 hover:bg-accent hover:text-accent-foreground",
                    value === employee.id && "bg-accent text-accent-foreground"
                  )}
                  onClick={() => handleOptionClick(employee.id)}
                >
                  <Avatar className="h-5 w-5 mr-2">
                    <AvatarFallback className="text-[10px]">
                      {getInitials(employee.firstName, employee.lastName)}
                    </AvatarFallback>
                  </Avatar>
                  <span>{employee.firstName} {employee.lastName}</span>
                  {value === employee.id && (
                    <Check className="ml-auto h-4 w-4" />
                  )}
                </div>
              ))
            )}
          </div>
        </div>
      )}
    </div>
  );
}

// Custom Project Dropdown component
interface CustomProjectDropdownProps {
  value?: number;
  onChange: (value: number) => void;
  projects: Array<{id: number; projectName: string; projectCode: string}>;
  isLoading: boolean;
  placeholder: string;
}

function CustomProjectDropdown({ value, onChange, projects, isLoading, placeholder }: CustomProjectDropdownProps) {
  const [open, setOpen] = useState(false);
  const [searchTerm, setSearchTerm] = useState("");
  
  const getProjectName = (id?: number) => {
    if (!id) return placeholder;
    const project = projects.find(proj => proj.id === id);
    return project ? project.projectName : `Project ${id}`;
  };
  
  const handleButtonClick = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setOpen(!open);
  };
  
  const handleOptionClick = (projectId: number) => {
    onChange(projectId);
    setOpen(false);
  };
  
  // Filter projects based on search term
  const filteredProjects = searchTerm
    ? projects.filter(
        proj => 
          proj.projectName.toLowerCase().includes(searchTerm.toLowerCase()) ||
          proj.projectCode.toLowerCase().includes(searchTerm.toLowerCase())
      )
    : projects;
  
  return (
    <div className="relative w-full">
      <div
        className={cn(
          "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background cursor-pointer",
          open && "ring-2 ring-ring ring-offset-2"
        )}
        onClick={handleButtonClick}
      >
        <div className="flex items-center">
          {!value && <Briefcase className="h-4 w-4 mr-2 opacity-50" />}
          {value && <Briefcase className="h-4 w-4 mr-2" />}
          <span className={!value ? "text-muted-foreground truncate" : "truncate"}>
            {getProjectName(value)}
          </span>
        </div>
        <ChevronDown className="h-4 w-4 shrink-0 opacity-50" />
      </div>
      
      {open && (
        <div className="absolute z-50 mt-1 w-full overflow-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md">
          <div className="flex items-center border-b px-3 py-2">
            <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
            <input
              className="flex h-8 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
              placeholder="Search project..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              onClick={(e) => e.stopPropagation()}
            />
          </div>
          
          <div className="max-h-60 overflow-auto py-1">
            {isLoading ? (
              <div className="flex items-center justify-center p-4">
                <Loader2 className="h-4 w-4 animate-spin" />
                <span className="ml-2">Loading...</span>
              </div>
            ) : filteredProjects.length === 0 ? (
              <div className="text-center p-2 text-sm text-muted-foreground">
                No project found
              </div>
            ) : (
              filteredProjects.map((project) => (
                <div
                  key={project.id}
                  className={cn(
                    "flex cursor-pointer items-center px-2 py-1.5 hover:bg-accent hover:text-accent-foreground",
                    value === project.id && "bg-accent text-accent-foreground"
                  )}
                  onClick={() => handleOptionClick(project.id)}
                >
                  <Briefcase className="h-4 w-4 mr-2" />
                  <span>{project.projectName}</span>
                  <span className="ml-2 text-xs text-muted-foreground">
                    ({project.projectCode})
                  </span>
                  {value === project.id && (
                    <Check className="ml-auto h-4 w-4" />
                  )}
                </div>
              ))
            )}
          </div>
        </div>
      )}
    </div>
  );
}

// Custom DatePicker component
interface CustomDatePickerProps {
  value: Date;
  onChange: (date: Date) => void;
}

function CustomDatePicker({ value, onChange }: CustomDatePickerProps) {
  const [open, setOpen] = useState(false);
  
  const handleButtonClick = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setOpen(!open);
  };
  
  return (
    <div className="relative w-full">
      <div
        className={cn(
          "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background cursor-pointer",
          open && "ring-2 ring-ring ring-offset-2"
        )}
        onClick={handleButtonClick}
      >
        {value ? format(value, "PPP") : <span className="text-muted-foreground">Pick a date</span>}
        <CalendarIcon className="h-4 w-4 shrink-0 opacity-50" />
      </div>
      
      {open && (
        <div className="absolute z-50 mt-1 overflow-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md">
          <Calendar
            mode="single"
            selected={value}
            onSelect={(date) => {
              if (date) {
                onChange(date);
                setOpen(false);
              }
            }}
            initialFocus
          />
        </div>
      )}
    </div>
  );
}

const todoSchema = z.object({
  title: z.string().min(3, { message: "Title must be at least 3 characters" }),
  description: z.string().min(5, { message: "Description must be at least 5 characters" }),
  status: z.enum(["Pending", "In Progress", "Completed"], {
    required_error: "Please select a status",
  }),
  priority: z.enum(["Low", "Medium", "High"], {
    required_error: "Please select a priority",
  }),
  dueDate: z.date({
    required_error: "Due date is required",
  }),
  assigneeId: z.number().optional(),
  projectId: z.number().optional(),
});

type TodoFormValues = z.infer<typeof todoSchema>;

type TodoFormProps = {
  todo?: Todo;
  onSubmit: (data: TodoCreateRequest | TodoUpdateRequest) => void;
  onCancel: () => void;
  isLoading?: boolean;
};

const statusOptions = [
  { value: "Pending", label: "Pending" },
  { value: "In Progress", label: "In Progress" },
  { value: "Completed", label: "Completed" },
];

const priorityOptions = [
  { value: "Low", label: "Low", color: "bg-green-100 text-green-800" },
  { value: "Medium", label: "Medium", color: "bg-yellow-100 text-yellow-800" },
  { value: "High", label: "High", color: "bg-red-100 text-red-800" },
];

type Employee = {
  id: number;
  firstName: string;
  lastName: string;
  email: string;
};

type Project = {
  id: number;
  projectName: string;
  projectCode: string;
};

export function TodoForm({ todo, onSubmit, onCancel, isLoading = false }: TodoFormProps) {
  const { userData } = useAuth();
  const [employees, setEmployees] = useState<Employee[]>([]);
  const [projects, setProjects] = useState<Project[]>([]);
  const [loadingEmployees, setLoadingEmployees] = useState(false);
  const [loadingProjects, setLoadingProjects] = useState(false);

  // Initialize form with default values or the provided todo
  const form = useForm<TodoFormValues>({
    resolver: zodResolver(todoSchema),
    defaultValues: {
      title: "",
      description: "",
      status: "Pending",
      priority: "Medium",
      dueDate: new Date(),
      assigneeId: undefined,
      projectId: undefined,
    },
  });

  // Fetch employees and projects
  useEffect(() => {
    const fetchEmployees = async () => {
      setLoadingEmployees(true);
      try {
        const response = await employeeService.getAll();
        if (Array.isArray(response)) {
          setEmployees(response);
        }
      } catch (error) {
        console.error("Failed to fetch employees:", error);
      } finally {
        setLoadingEmployees(false);
      }
    };

    const fetchProjects = async () => {
      setLoadingProjects(true);
      try {
        const response = await projectService.getAll();
        if (Array.isArray(response)) {
          setProjects(response);
        }
      } catch (error) {
        console.error("Failed to fetch projects:", error);
      } finally {
        setLoadingProjects(false);
      }
    };

    fetchEmployees();
    fetchProjects();
  }, []);

  // Update form values when todo changes
  useEffect(() => {
    if (todo) {
      form.reset({
        title: todo.title,
        description: todo.description,
        status: todo.status,
        priority: todo.priority,
        dueDate: new Date(todo.dueDate),
        assigneeId: todo.assigneeId,
        projectId: todo.projectId,
      });
    }
  }, [todo, form]);

  const handleSubmit = (values: TodoFormValues) => {
    try {
      const todoData = {
        ...values,
        dueDate: format(values.dueDate, "yyyy-MM-dd"),
      };

      // If creating a new todo and no assignee is selected, use the current user's employeeId
      if (!todo && !values.assigneeId && userData?.employeeId) {
        todoData.assigneeId = userData.employeeId;
      }

      if (todo) {
        onSubmit({
          ...todoData,
          id: todo.id,
        } as TodoUpdateRequest);
      } else {
        onSubmit(todoData as TodoCreateRequest);
      }
    } catch (error) {
      console.error("Error submitting todo form:", error);
      // You can add additional error handling here if needed
    }
  };

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
        <FormField
          control={form.control}
          name="title"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Title</FormLabel>
              <FormControl>
                <Input placeholder="Enter todo title" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <FormField
          control={form.control}
          name="description"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Description</FormLabel>
              <FormControl>
                <Textarea
                  placeholder="Enter todo description"
                  className="resize-none"
                  {...field}
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <FormField
            control={form.control}
            name="status"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Status</FormLabel>
                <FormControl>
                  <CustomDropdown 
                    value={field.value}
                    onChange={field.onChange}
                    options={statusOptions}
                    placeholder="Select status"
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="priority"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Priority</FormLabel>
                <FormControl>
                  <CustomDropdown 
                    value={field.value}
                    onChange={field.onChange}
                    options={priorityOptions}
                    placeholder="Select priority"
                    showBadge={true}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
        </div>

        <FormField
          control={form.control}
          name="dueDate"
          render={({ field }) => (
            <FormItem className="flex flex-col">
              <FormLabel>Due Date</FormLabel>
              <FormControl>
                <CustomDatePicker
                  value={field.value}
                  onChange={field.onChange}
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <FormField
            control={form.control}
            name="assigneeId"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Assignee</FormLabel>
                <FormControl>
                  <CustomEmployeeDropdown
                    value={field.value}
                    onChange={field.onChange}
                    employees={employees}
                    isLoading={loadingEmployees}
                    placeholder="Select assignee"
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="projectId"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Project</FormLabel>
                <FormControl>
                  <CustomProjectDropdown
                    value={field.value}
                    onChange={field.onChange}
                    projects={projects}
                    isLoading={loadingProjects}
                    placeholder="Select project"
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
        </div>

        <div className="flex items-center justify-end space-x-4 pt-4">
          <Button type="button" variant="outline" onClick={onCancel} disabled={isLoading}>
            Cancel
          </Button>
          <Button type="submit" disabled={isLoading}>
            {isLoading ? "Saving..." : todo ? "Update Todo" : "Create Todo"}
          </Button>
        </div>
      </form>
    </Form>
  );
} 