import React, { useState, useRef, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { format } from 'date-fns';
import { Button } from '@/components/ui/button';
import { Textarea } from '@/components/ui/textarea';
import { Calendar } from '@/components/ui/calendar';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  FormDescription,
} from '@/components/ui/form';
import { SearchableDropdown } from './shared/SearchableDropdown';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Loader2, Save, X, Calendar as CalendarIcon, User } from 'lucide-react';

import {
  AssetAssignment,
  AssetAssignmentCreateRequest,
  AssetAssignmentUpdateRequest,
  AssetAssignmentFormSchema,
} from '@/types/asset-management';
import { Employee } from '@/types';
import { useAssets } from '@/hooks/asset-management/useAssets';

// Custom DatePicker component that works in modals
interface CustomDatePickerProps {
  value: Date | null;
  onChange: (date: Date | null) => void;
  placeholder?: string;
  disabled?: (date: Date) => boolean;
}

const CustomDatePicker: React.FC<CustomDatePickerProps> = ({
  value,
  onChange,
  placeholder = "Pick a date",
  disabled
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const datePickerRef = useRef<HTMLDivElement>(null);

  // Close date picker when clicking outside
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (datePickerRef.current && !datePickerRef.current.contains(event.target as Node)) {
        setIsOpen(false);
      }
    };

    if (isOpen) {
      document.addEventListener("mousedown", handleClickOutside);
      return () => {
        document.removeEventListener("mousedown", handleClickOutside);
      };
    }
  }, [isOpen]);

  return (
    <div className="relative w-full" ref={datePickerRef}>
      <button
        type="button"
        onClick={() => setIsOpen(!isOpen)}
        className="flex w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 min-h-[44px] md:min-h-[40px] touch-manipulation"
        aria-label={value ? `Selected date: ${format(value, "PPP")}` : placeholder}
      >
        <span className={value ? "" : "text-muted-foreground"}>
          {value ? format(value, "PPP") : placeholder}
        </span>
        <CalendarIcon className="h-4 w-4 opacity-50" />
      </button>

      {isOpen && (
        <div className="fixed inset-0 z-[99999] flex justify-center items-center bg-black/50 overflow-auto">
          <div className="bg-background border rounded-lg p-4 shadow-lg max-w-sm w-full mx-4">
            <div className="flex justify-between items-center mb-2">
              <h3 className="text-base font-medium">Select Date</h3>
              <Button
                variant="ghost"
                size="sm"
                className="h-8 w-8 p-0"
                onClick={() => setIsOpen(false)}
              >
                <X className="h-4 w-4" />
              </Button>
            </div>
            <Calendar
              mode="single"
              selected={value || undefined}
              onSelect={(date) => {
                onChange(date || null);
                setIsOpen(false);
              }}
              disabled={disabled}
              initialFocus
              className="rounded border"
            />
            <div className="mt-2 flex justify-end gap-2">
              <Button
                size="sm"
                variant="outline"
                onClick={() => {
                  onChange(null);
                  setIsOpen(false);
                }}
                className="min-h-[44px] md:min-h-0 touch-manipulation"
                aria-label="Clear date selection"
              >
                Clear
              </Button>
              <Button
                size="sm"
                variant="outline"
                onClick={() => setIsOpen(false)}
                className="min-h-[44px] md:min-h-0 touch-manipulation"
                aria-label="Close date picker"
              >
                Close
              </Button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

interface AssignmentFormProps {
  assignment?: AssetAssignment;
  preselectedAssetId?: number;
  preselectedEmployeeId?: number;
  employees?: Employee[];
  onSubmit: (data: AssetAssignmentCreateRequest | AssetAssignmentUpdateRequest) => Promise<void>;
  onCancel: () => void;
  isSubmitting?: boolean;
  title?: string;
}

type AssignmentFormValues = {
  assetID: number;
  employeeID: number;
  employeeName: string;
  assetCode: string;
  assignedDate: Date;
  returnedDate: Date | null;
  remarks: string;
};

const AssignmentForm: React.FC<AssignmentFormProps> = ({
  assignment,
  preselectedAssetId,
  preselectedEmployeeId,
  employees = [],
  onSubmit,
  onCancel,
  isSubmitting = false,
  title
}) => {
  const isEditing = !!assignment;
  const formTitle = title || (isEditing ? 'Edit Assignment' : 'Create New Assignment');

  const { data: assets = [], isLoading: isLoadingAssets } = useAssets();
  const employeeFieldRef = useRef<HTMLButtonElement>(null);

  const form = useForm<AssignmentFormValues>({
    resolver: zodResolver(AssetAssignmentFormSchema),
    defaultValues: {
      assetID: assignment?.assetID || preselectedAssetId || 0,
      employeeID: assignment?.employeeID || preselectedEmployeeId || 0,
      employeeName: assignment?.employeeName || '',
      assetCode: assignment?.assetCode || '',
      assignedDate: assignment ? new Date(assignment.assignedDate) : new Date(),
      returnedDate: assignment?.returnedDate ? new Date(assignment.returnedDate) : null,
      remarks: assignment?.remarks || '',
    },
  });

  // Get preselected asset details
  const preselectedAsset = preselectedAssetId 
    ? assets.find(a => a.assetID === preselectedAssetId)
    : null;

  // Auto-populate asset field when preselectedAssetId is provided
  useEffect(() => {
    if (preselectedAssetId && assets.length > 0 && !assignment) {
      const asset = assets.find(a => a.assetID === preselectedAssetId);
      if (asset) {
        form.setValue('assetID', asset.assetID);
        form.setValue('assetCode', asset.assetCode);
      }
    }
  }, [preselectedAssetId, assets, assignment, form]);

  // Auto-focus employee selection field when asset is pre-selected
  useEffect(() => {
    if (preselectedAssetId && !assignment && employeeFieldRef.current) {
      // Small delay to ensure the form is fully rendered
      const timer = setTimeout(() => {
        employeeFieldRef.current?.focus();
      }, 100);
      return () => clearTimeout(timer);
    }
  }, [preselectedAssetId, assignment]);

  const handleSubmit = async (values: AssignmentFormValues) => {
    try {
      // Validate dates before submission
      if (values.returnedDate && values.returnedDate <= values.assignedDate) {
        form.setError('returnedDate', {
          type: 'manual',
          message: 'Returned date must be after the assigned date.'
        });
        return;
      }

      // Convert dates to ISO strings
      const assignedDateISO = values.assignedDate.toISOString();
      const returnedDateISO = values.returnedDate ? values.returnedDate.toISOString() : null;

      if (isEditing && assignment) {
        const updateData: AssetAssignmentUpdateRequest = {
          assignmentID: assignment.assignmentID,
          assetID: values.assetID,
          employeeID: values.employeeID,
          employeeName: values.employeeName,
          assetCode: values.assetCode,
          assignedDate: assignedDateISO,
          returnedDate: returnedDateISO,
          remarks: values.remarks,
        };
        await onSubmit(updateData);
      } else {
        const createData: AssetAssignmentCreateRequest = {
          assetID: values.assetID,
          employeeID: values.employeeID,
          employeeName: values.employeeName,
          assetCode: values.assetCode,
          assignedDate: assignedDateISO,
          returnedDate: returnedDateISO,
          remarks: values.remarks,
        };
        await onSubmit(createData);
      }
    } catch (error) {
      console.error('Form submission error:', error);

      // Set form errors if validation failed
      if (error instanceof Error) {
        if (error.message.includes('Asset with ID') && error.message.includes('does not exist')) {
          form.setError('assetID', {
            type: 'manual',
            message: 'The selected asset does not exist. Please select a valid asset.'
          });
        } else if (error.message.includes('Employee with ID') && error.message.includes('does not exist')) {
          form.setError('employeeID', {
            type: 'manual',
            message: 'The selected employee does not exist. Please select a valid employee.'
          });
        } else if (error.message.includes('already assigned')) {
          form.setError('assetID', {
            type: 'manual',
            message: 'This asset is already assigned to another employee. Please select a different asset or return the current assignment first.'
          });
        } else if (error.message.includes('date')) {
          form.setError('assignedDate', {
            type: 'manual',
            message: 'Invalid date format. Please select a valid date.'
          });
        } else {
          // Set a general form error
          form.setError('root', {
            type: 'manual',
            message: error.message
          });
        }
      }
    }
  };

  const getEmployeeDisplayName = (employee: Employee) => {
    return `${employee.firstName} ${employee.lastName}`;
  };

  return (
    <Card className="w-full mx-auto">
      <CardHeader>
        <CardTitle className="flex items-center gap-2">
          <User className="h-5 w-5" />
          {formTitle}
        </CardTitle>
      </CardHeader>
      <CardContent>
        <Form {...form}>
          <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
            {/* Display form-level errors */}
            {form.formState.errors.root && (
              <div className="bg-destructive/15 border border-destructive/20 rounded-md p-3">
                <p className="text-sm text-destructive font-medium">
                  {form.formState.errors.root.message}
                </p>
              </div>
            )}

            {/* Display pre-selected asset information prominently */}
            {preselectedAsset && !assignment && (
              <div className="bg-primary/5 border border-primary/20 rounded-lg p-4">
                <div className="flex items-start gap-3">
                  <div className="flex-shrink-0 w-10 h-10 bg-primary/10 rounded-full flex items-center justify-center">
                    <User className="h-5 w-5 text-primary" />
                  </div>
                  <div className="flex-1 min-w-0">
                    <h4 className="text-sm font-semibold text-foreground mb-1">
                      Assigning Asset
                    </h4>
                    <div className="space-y-1">
                      <p className="text-sm text-muted-foreground">
                        <span className="font-medium text-foreground">Code:</span> {preselectedAsset.assetCode}
                      </p>
                      <p className="text-sm text-muted-foreground">
                        <span className="font-medium text-foreground">Type:</span> {preselectedAsset.assetType}
                      </p>
                      <p className="text-sm text-muted-foreground">
                        <span className="font-medium text-foreground">Model:</span> {preselectedAsset.brandModel}
                      </p>
                    </div>
                  </div>
                </div>
              </div>
            )}

            <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
              {/* Asset Selection */}
              <FormField
                control={form.control}
                name="assetID"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>Asset *</FormLabel>
                    <FormDescription>
                      {preselectedAssetId && !assignment 
                        ? 'Asset is pre-selected for this assignment.'
                        : 'Select the asset to assign to the employee.'}
                    </FormDescription>
                    <FormControl>
                      <SearchableDropdown
                        options={assets.map(asset => ({
                          value: asset.assetID.toString(),
                          label: `${asset.assetCode} - ${asset.assetType} - ${asset.brandModel}`
                        }))}
                        value={field.value?.toString() || ''}
                        onChange={(value) => {
                          const assetId = parseInt(value);
                          field.onChange(assetId);
                          // Auto-populate asset code when asset is selected
                          const selectedAsset = assets.find(asset => asset.assetID === assetId);
                          if (selectedAsset) {
                            form.setValue('assetCode', selectedAsset.assetCode);
                          }
                        }}
                        placeholder="Select an asset"
                        searchPlaceholder="Search assets by code, type, or model..."
                        disabled={isLoadingAssets || (!!preselectedAssetId && !assignment)}
                        error={!!form.formState.errors.assetID}
                        aria-label="Asset selection"
                        aria-describedby={form.formState.errors.assetID ? 'assetID-error' : undefined}
                        emptyMessage="No assets found matching your search"
                      />
                    </FormControl>
                    <FormMessage id="assetID-error" />
                  </FormItem>
                )}
              />

              {/* Employee Selection */}
              <FormField
                control={form.control}
                name="employeeID"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>Employee *</FormLabel>
                    <FormDescription>
                      Select the employee to assign the asset to.
                    </FormDescription>
                    <FormControl>
                      <div ref={(el) => {
                        if (el && preselectedAssetId && !assignment) {
                          const trigger = el.querySelector('[role="combobox"]') as HTMLElement;
                          if (trigger) {
                            (employeeFieldRef as any).current = trigger;
                          }
                        }
                      }}>
                        <SearchableDropdown
                          options={employees.map(employee => ({
                            value: employee.id.toString(),
                            label: `#${employee.empCode} - ${getEmployeeDisplayName(employee)} - ${employee.email}`
                          }))}
                          value={field.value?.toString() || ''}
                          onChange={(value) => {
                            const employeeId = parseInt(value);
                            field.onChange(employeeId);
                            // Auto-populate employee name when employee is selected
                            const selectedEmployee = employees.find(employee => employee.id === employeeId);
                            if (selectedEmployee) {
                              form.setValue('employeeName', getEmployeeDisplayName(selectedEmployee));
                            }
                          }}
                          placeholder="Select an employee"
                          searchPlaceholder="Search employees by name, email, or ID..."
                          error={!!form.formState.errors.employeeID}
                          aria-label="Employee selection"
                          aria-describedby={form.formState.errors.employeeID ? 'employeeID-error' : undefined}
                          emptyMessage="No employees found matching your search"
                        />
                      </div>
                    </FormControl>
                    <FormMessage id="employeeID-error" />
                  </FormItem>
                )}
              />

              {/* Employee Name (Auto-populated) */}
              <FormField
                control={form.control}
                name="employeeName"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>Employee Name *</FormLabel>
                    <FormControl>
                      <input
                        {...field}
                        type="text"
                        placeholder="Employee name will be auto-populated"
                        className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
                        readOnly
                      />
                    </FormControl>
                    <FormDescription>
                      This field is automatically populated when you select an employee.
                    </FormDescription>
                    <FormMessage />
                  </FormItem>
                )}
              />

              {/* Asset Code (Auto-populated) */}
              <FormField
                control={form.control}
                name="assetCode"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>Asset Code *</FormLabel>
                    <FormControl>
                      <input
                        {...field}
                        type="text"
                        placeholder="Asset code will be auto-populated"
                        className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
                        readOnly
                      />
                    </FormControl>
                    <FormDescription>
                      This field is automatically populated when you select an asset.
                    </FormDescription>
                    <FormMessage />
                  </FormItem>
                )}
              />

              {/* Assigned Date */}
              <FormField
                control={form.control}
                name="assignedDate"
                render={({ field }) => (
                  <FormItem className="flex flex-col">
                    <FormLabel>Assigned Date *</FormLabel>
                    <FormControl>
                      <CustomDatePicker
                        value={field.value}
                        onChange={field.onChange}
                        placeholder="Pick a date"
                        disabled={(date) => date < new Date("1900-01-01")}
                      />
                    </FormControl>
                    <FormDescription>
                      The date when the asset was assigned to the employee.
                    </FormDescription>
                    <FormMessage />
                  </FormItem>
                )}
              />

              {/* Returned Date */}
              <FormField
                control={form.control}
                name="returnedDate"
                render={({ field }) => (
                  <FormItem className="flex flex-col">
                    <FormLabel>Returned Date</FormLabel>
                    <FormControl>
                      <CustomDatePicker
                        value={field.value}
                        onChange={field.onChange}
                        placeholder="Not returned yet"
                        disabled={(date) => {
                          const assignedDate = form.getValues('assignedDate');
                          return (
                            date < new Date("1900-01-01") ||
                            (assignedDate && date < assignedDate)
                          );
                        }}
                      />
                    </FormControl>
                    <FormDescription>
                      Leave empty if the asset is still assigned. The returned date must be after the assigned date.
                    </FormDescription>
                    <FormMessage />
                  </FormItem>
                )}
              />
            </div>

            {/* Remarks */}
            <FormField
              control={form.control}
              name="remarks"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Remarks *</FormLabel>
                  <FormControl>
                    <Textarea
                      placeholder="Enter any additional notes about this assignment..."
                      className="min-h-20"
                      {...field}
                    />
                  </FormControl>
                  <FormDescription>
                    Provide any relevant information about this assignment (purpose, conditions, etc.).
                  </FormDescription>
                  <FormMessage />
                </FormItem>
              )}
            />

            {/* Form Actions */}
            <div className="flex flex-col sm:flex-row justify-end gap-3 pt-4">
              <Button
                type="button"
                variant="outline"
                onClick={onCancel}
                disabled={isSubmitting}
                className="flex items-center justify-center gap-2 min-h-[44px] md:min-h-0 touch-manipulation w-full sm:w-auto"
                aria-label="Cancel assignment form"
              >
                <X className="h-4 w-4" />
                <span>Cancel</span>
              </Button>
              <Button
                type="submit"
                disabled={isSubmitting}
                className="flex items-center justify-center gap-2 min-h-[44px] md:min-h-0 touch-manipulation w-full sm:w-auto"
                aria-label={isEditing ? 'Update assignment' : 'Create assignment'}
              >
                {isSubmitting ? (
                  <Loader2 className="h-4 w-4 animate-spin" />
                ) : (
                  <Save className="h-4 w-4" />
                )}
                <span>
                  {isSubmitting
                    ? (isEditing ? 'Updating...' : 'Creating...')
                    : (isEditing ? 'Update Assignment' : 'Create Assignment')
                  }
                </span>
              </Button>
            </div>
          </form>
        </Form>
      </CardContent>
    </Card>
  );
};

export default AssignmentForm;