import React, { useState, useCallback, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Upload, FileText, AlertCircle, Download } from "lucide-react";
import { toast } from "sonner";
import { tasksApi, TaskCreateRequest } from "@/services/tasksApi";
import { employeeService, projectService, issuesApi } from "@/lib/api";
import * as XLSX from 'xlsx';
import { Employee, ProjectApi, IssueApi } from "@/types";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Progress } from "@/components/ui/progress";
import CustomDialog from "@/components/CustomDialog";
import { Dropdown } from "@/components/ui/dropdown";

interface ImportTasksDialogProps {
  taskType: "Bug" | "Test Case";
  projectId?: number;
  onImportComplete: () => void;
}

interface PreviewData {
  preview: any[];
  total: number;
  all: any[];
}

const ImportTasksDialog: React.FC<ImportTasksDialogProps> = ({ 
  taskType,
  projectId, 
  onImportComplete 
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [previewData, setPreviewData] = useState<PreviewData | null>(null);
  const [fileName, setFileName] = useState<string>("");
  
  // State for data from APIs
  const [loading, setLoading] = useState(false);
  const [employees, setEmployees] = useState<Employee[]>([]);
  const [projects, setProjects] = useState<ProjectApi[]>([]);
  const [issues, setIssues] = useState<IssueApi[]>([]);
  const [filteredIssues, setFilteredIssues] = useState<IssueApi[]>([]);
  
  // Selected values
  const [selectedAssignedTo, setSelectedAssignedTo] = useState<number | "">("");
  const [selectedProjectId, setSelectedProjectId] = useState<number | "">(projectId || "");
  const [selectedIssueId, setSelectedIssueId] = useState<number | "">("");

  // Get default status based on task type
  const getDefaultStatus = () => {
    if (taskType === "Bug") {
      return "Open";
    } else {
      return "Draft";
    }
  };

  // Fetch initial data
  useEffect(() => {
    const fetchInitialData = async () => {
      if (!isOpen) return;
      
      setLoading(true);
      try {
        const [employeeData, projectData, issuesData] = await Promise.all([
          employeeService.getAll(),
          projectService.getAll(),
          issuesApi.getAll()
        ]);
        
        setEmployees(employeeData);
        setProjects(projectData);
        setIssues(issuesData);
        
        if (projectId) {
          setSelectedProjectId(projectId);
        }
      } catch (error) {
        console.error("Error fetching data:", error);
        toast.error("Failed to load data");
      } finally {
        setLoading(false);
      }
    };
    
    fetchInitialData();
  }, [isOpen, projectId]);

  // Filter issues based on selected project
  useEffect(() => {
    if (selectedProjectId && typeof selectedProjectId === 'number') {
      const filtered = issues.filter(issue => issue.projectId === selectedProjectId);
      setFilteredIssues(filtered);
      // Reset selected issue if it's not in the filtered list
      if (selectedIssueId && !filtered.find(issue => issue.id === selectedIssueId)) {
        setSelectedIssueId("");
      }
    } else {
      setFilteredIssues(issues);
    }
  }, [selectedProjectId, issues, selectedIssueId]);

  // Template Excel download handler
  const handleDownloadTemplate = () => {
    const headers = taskType === "Bug" 
      ? [
          "Title", 
          "Description", 
          "Issue/Feature ID (Required)",
          "Priority", 
          "Severity", 
          "Assigned To (Employee ID - Optional)", 
          "Project ID (Optional)",
          "Version (Optional)",
          "Environment (Optional)",
          "Steps To Reproduce (Optional)",
          "Expected Behavior (Optional)",
          "Actual Behavior (Optional)"
        ]
      : [
          "Title", 
          "Description", 
          "Issue/Feature ID (Required)",
          "Priority", 
          "Severity", 
          "Assigned To (Employee ID - Optional)", 
          "Project ID (Optional)",
          "Version (Optional)",
          "Test Steps (Optional)",
          "Expected Result (Optional)",
          "Actual Result (Optional)"
        ];
    
    const sampleData = taskType === "Bug"
      ? [
          [
            "Sample Bug Title",
            "Description of the bug",
            "1", // Issue/Feature ID - Required (use actual ID from your issues list)
            "High", // Priority: Low, Medium, High, Critical
            "Major", // Severity: Critical, Major, Minor, Trivial
            "", // Assigned To (Employee ID) - Optional
            projectId || "", // Project ID - Optional
            "1.0.0", // Version
            "Production", // Environment
            "1. Step one\n2. Step two", // Steps to reproduce
            "Expected behavior description", // Expected Behavior
            "Actual behavior description" // Actual Behavior
          ]
        ]
      : [
          [
            "Sample Test Case Title",
            "Description of the test case",
            "1", // Issue/Feature ID - Required (use actual ID from your issues list)
            "High", // Priority: Low, Medium, High, Critical
            "High", // Severity: High, Medium, Low
            "", // Assigned To (Employee ID) - Optional
            projectId || "", // Project ID - Optional
            "1.0.0", // Version
            "1. Test step one\n2. Test step two", // Test Steps
            "Expected result description", // Expected Result
            "Actual result description" // Actual Result
          ]
        ];
    
    const workbook = XLSX.utils.book_new();
    const worksheet = XLSX.utils.aoa_to_sheet([headers, ...sampleData]);
    
    // Set column widths
    worksheet['!cols'] = headers.map(() => ({ wch: 20 }));
    
    XLSX.utils.book_append_sheet(workbook, worksheet, taskType === "Bug" ? "Bugs" : "Test Cases");
    
    const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
    const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.setAttribute('href', url);
    link.setAttribute('download', `${taskType.toLowerCase().replace(' ', '_')}_import_template.xlsx`);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    
    toast.success("Template downloaded successfully");
  };

  const handleFileUpload = useCallback(async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) {
      return;
    }

    const fileExtension = file.name.split('.').pop()?.toLowerCase();
    if (fileExtension !== 'xlsx' && fileExtension !== 'xls') {
      const errorMsg = "Invalid file type. Please upload an Excel file (.xlsx or .xls).";
      setError(errorMsg);
      toast.error(errorMsg);
      return;
    }

    if (file.size > 10 * 1024 * 1024) {
      const errorMsg = "File size too large. Maximum size is 10MB";
      setError(errorMsg);
      toast.error(errorMsg);
      return;
    }

    setFileName(file.name);
    setError(null);
    setPreviewData(null);
    setIsUploading(true);

    try {
      const reader = new FileReader();
      reader.onload = (e) => {
        try {
          const data = new Uint8Array(e.target?.result as ArrayBuffer);
          const workbook = XLSX.read(data, { type: 'array' });
          
          const firstSheetName = workbook.SheetNames[0];
          const worksheet = workbook.Sheets[firstSheetName];
          const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
          
          if (jsonData.length <= 1) {
            setError("The Excel file contains no data rows.");
            setIsUploading(false);
            return;
          }
          
          const headers = jsonData[0] as string[];
          const rows = [];
          
          for (let i = 1; i < jsonData.length; i++) {
            const row = jsonData[i] as any[];
            const obj: any = {};
            
            for (let j = 0; j < headers.length; j++) {
              obj[headers[j]] = row[j] || "";
            }
            
            rows.push(obj);
          }
          
          const requiredFields = ["Title", "Description", "Issue/Feature ID (Required)"];
          const missingFields = requiredFields.filter(field => 
            !headers.includes(field)
          );

          if (missingFields.length > 0) {
            setError(`Missing required columns: ${missingFields.join(', ')}`);
            setIsUploading(false);
            return;
          }
          
          const allRows = [...rows];
          const previewRows = rows.slice(0, 10);
          
          setPreviewData({
            preview: previewRows,
            total: allRows.length,
            all: allRows
          });
          
          toast.success(`Excel file loaded with ${allRows.length} ${taskType.toLowerCase()}s ready to import`);
          setIsUploading(false);
        } catch (error) {
          console.error('Excel parsing error:', error);
          setError("Failed to parse Excel file. Please check the file format.");
          toast.error("Failed to parse Excel file");
          setIsUploading(false);
        }
      };
      
      reader.readAsArrayBuffer(file);
    } catch (error) {
      console.error('File reading error:', error);
      setError("Failed to read the file. Please try again.");
      toast.error("Failed to read the file");
      setIsUploading(false);
    }
  }, [taskType]);

  const handleImport = useCallback(async () => {
    if (!previewData?.all?.length) {
      toast.error("No data to import");
      return;
    }

    setIsUploading(true);
    setError(null);
    setUploadProgress(10);

    try {
      const allTasks = previewData.all;
      const progressStep = 80 / allTasks.length;
      let successCount = 0;
      let failureCount = 0;
      
      for (let i = 0; i < allTasks.length; i++) {
        const taskData = allTasks[i] as Record<string, any>;
        try {
          const issueId = selectedIssueId || parseInt(String(taskData["Issue/Feature ID (Required)"])) || null;
          
          // Skip if missing required issue/feature ID
          if (!issueId) {
            console.error(`Row ${i + 1}: Missing required Issue/Feature ID`);
            failureCount++;
            continue;
          }
          
          const taskRequest: TaskCreateRequest = {
            type: taskType,
            title: taskData.Title || "",
            description: taskData.Description || "",
            priority: taskData.Priority || "Medium",
            severity: taskData.Severity || (taskType === "Bug" ? "Minor" : "Medium"),
            status: getDefaultStatus(),
            assignedTo: selectedAssignedTo || parseInt(String(taskData["Assigned To (Employee ID - Optional)"])) || null,
            issuesId: issueId,
            version: taskData["Version (Optional)"] || "",
            estimates: "0",
            esUnit: 1,
            remainingHr: 0,
            stateDate: new Date().toISOString(),
            endDate: null,
            sprintName: null,
          };

          // Add bug-specific fields
          if (taskType === "Bug") {
            taskRequest.environment = taskData["Environment (Optional)"] || "";
            taskRequest.stepsToReproduce = taskData["Steps To Reproduce (Optional)"] || "";
            taskRequest.expectedBehavior = taskData["Expected Behavior (Optional)"] || "";
            taskRequest.actualBehavior = taskData["Actual Behavior (Optional)"] || "";
          } else {
            // Test case specific fields
            taskRequest.stepsToReproduce = taskData["Test Steps (Optional)"] || "";
            taskRequest.expectedBehavior = taskData["Expected Result (Optional)"] || "";
            taskRequest.actualBehavior = taskData["Actual Result (Optional)"] || "";
          }
          
          if (!taskRequest.title) {
            failureCount++;
            continue;
          }
          
          await tasksApi.create(taskRequest);
          successCount++;
        } catch (error) {
          console.error(`Error importing ${taskType.toLowerCase()}:`, error);
          failureCount++;
        }
        
        setUploadProgress(10 + (i + 1) * progressStep);
      }
      
      setUploadProgress(100);
      
      if (successCount > 0) {
        toast.success(`Successfully imported ${successCount} ${taskType.toLowerCase()}${successCount > 1 ? 's' : ''}`);
        
        if (failureCount > 0) {
          toast.error(`Failed to import ${failureCount} ${taskType.toLowerCase()}${failureCount > 1 ? 's' : ''}`);
        }
        
        setTimeout(() => {
          setIsOpen(false);
          onImportComplete();
          setPreviewData(null);
          setFileName("");
          setUploadProgress(0);
          setSelectedAssignedTo("");
          setSelectedProjectId("");
          setSelectedIssueId("");
        }, 1500);
      } else {
        throw new Error(`Failed to import any ${taskType.toLowerCase()}s`);
      }
    } catch (error: any) {
      console.error('Import processing error:', error);
      setError(error.message || "Failed to process Excel data");
      toast.error(error.message || "Failed to process Excel data");
      setUploadProgress(0);
      setIsUploading(false);
    }
  }, [previewData, projectId, onImportComplete, selectedAssignedTo, selectedProjectId, selectedIssueId, taskType]);

  const renderContent = () => (
    <div className="flex-1 overflow-auto">
      <div className="flex flex-col space-y-4">
        <div className="mb-4 flex justify-between items-center">
          <Button 
            variant="outline" 
            size="sm" 
            onClick={handleDownloadTemplate}
            className="flex items-center gap-2"
          >
            <Download className="h-4 w-4" />
            Download Excel Template
          </Button>
          
          {fileName && previewData?.preview?.length > 0 && (
            <div className="text-sm text-muted-foreground">
              Showing {previewData.preview.length} of {previewData.total} {taskType.toLowerCase()}s
            </div>
          )}
        </div>
        
        {!fileName && (
          <div className="flex flex-col items-center justify-center border-2 border-dashed rounded-lg p-8">
            <input
              type="file"
              accept=".xlsx,.xls"
              onChange={handleFileUpload}
              className="hidden"
              id="task-excel-upload"
              disabled={isUploading}
            />
            <label
              htmlFor="task-excel-upload"
              className={`cursor-pointer flex flex-col items-center justify-center ${
                isUploading ? 'opacity-50 cursor-not-allowed' : ''
              }`}
            >
              <Upload className="h-12 w-12 mb-2 text-muted-foreground" />
              <span className="text-sm font-medium mb-1">Click to upload Excel file</span>
              <span className="text-xs text-muted-foreground">Supported formats: .xlsx, .xls (Max: 10MB)</span>
            </label>
          </div>
        )}
        
        {isUploading && !previewData && (
          <div className="flex justify-center py-8">
            <div className="animate-spin rounded-full h-12 w-12 border-4 border-primary border-t-transparent"></div>
          </div>
        )}
        
        {fileName && previewData?.preview?.length > 0 && (
          <div className="space-y-4">
            <div className="flex items-center p-3 bg-muted/50 rounded-md">
              <FileText className="h-5 w-5 mr-2 text-muted-foreground" />
              <span className="text-sm font-medium">{fileName}</span>
              
              {!isUploading && (
                <Button 
                  variant="ghost" 
                  size="sm" 
                  className="ml-auto"
                  onClick={() => {
                    setFileName("");
                    setPreviewData(null);
                    const input = document.getElementById("task-excel-upload") as HTMLInputElement;
                    if (input) input.value = "";
                  }}
                >
                  Change
                </Button>
              )}
            </div>
            
            <div className="border rounded-md p-4 bg-muted/20">
              <h4 className="text-sm font-medium mb-3">Set values for all {taskType.toLowerCase()}s:</h4>
              <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
                <div>
                  <label className="text-xs font-medium text-muted-foreground mb-1 block">
                    Assigned To
                  </label>
                  <Dropdown
                    options={[
                      { label: "— Select Assignee —", value: "" },
                      ...employees.map(emp => ({
                        label: `${emp.firstName} ${emp.lastName}`,
                        value: emp.id.toString()
                      }))
                    ]}
                    value={selectedAssignedTo ? selectedAssignedTo.toString() : ""}
                    onValueChange={(value) => setSelectedAssignedTo(value ? parseInt(value) : "")}
                    placeholder="Select Assignee"
                    disabled={isUploading || loading}
                    className="w-full"
                  />
                </div>
                
                <div>
                  <label className="text-xs font-medium text-muted-foreground mb-1 block">
                    Project
                  </label>
                  <Dropdown
                    options={[
                      { label: "— Select Project —", value: "" },
                      ...projects.map(proj => ({
                        label: proj.projectName,
                        value: proj.id.toString()
                      }))
                    ]}
                    value={selectedProjectId ? selectedProjectId.toString() : ""}
                    onValueChange={(value) => setSelectedProjectId(value ? parseInt(value) : "")}
                    placeholder="Select Project"
                    disabled={isUploading || loading}
                    className="w-full"
                  />
                </div>
                
                <div>
                  <label className="text-xs font-medium text-muted-foreground mb-1 block">
                    Issue/Feature <span className="text-red-500">*</span>
                  </label>
                  <Dropdown
                    options={[
                      { label: "— Select Issue/Feature —", value: "" },
                      ...filteredIssues.map(issue => ({
                        label: `${issue.biCode} - ${issue.title}`,
                        value: issue.id.toString()
                      }))
                    ]}
                    value={selectedIssueId ? selectedIssueId.toString() : ""}
                    onValueChange={(value) => setSelectedIssueId(value ? parseInt(value) : "")}
                    placeholder="Select Issue/Feature"
                    disabled={isUploading || loading}
                    className="w-full"
                  />
                </div>
              </div>
              <p className="text-xs text-muted-foreground mt-2">
                <span className="font-medium">Note:</span> Issue/Feature is mandatory for all {taskType.toLowerCase()}s. 
                If set here, it will override values in the imported file. Otherwise, each row must have a valid Issue/Feature ID.
              </p>
            </div>
            
            <div className="space-y-2">
              <div className="flex justify-between items-center">
                <h4 className="text-sm font-medium">Preview rows:</h4>
                <Button
                  variant="ghost" 
                  size="sm"
                  className="text-xs"
                  onClick={() => {
                    setFileName("");
                    setPreviewData(null);
                    const input = document.getElementById("task-excel-upload") as HTMLInputElement;
                    if (input) input.value = "";
                  }}
                >
                  Upload Different File
                </Button>
              </div>
              <div className="border rounded-md overflow-auto" style={{ maxHeight: "300px" }}>
                <table className="min-w-full divide-y divide-border">
                  <thead className="bg-muted/50 sticky top-0 z-10">
                    <tr>
                      {previewData?.preview?.length > 0 && Object.keys(previewData.preview[0]).map((header) => (
                        <th 
                          key={header} 
                          className="px-3 py-2 text-xs font-medium text-muted-foreground text-left"
                        >
                          {header}
                        </th>
                      ))}
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-border">
                    {previewData?.preview?.map((row, rowIndex) => (
                      <tr key={rowIndex} className={rowIndex % 2 === 0 ? "bg-muted/20" : ""}>
                        {Object.values(row).map((cell: any, cellIndex) => (
                          <td 
                            key={cellIndex} 
                            className="px-3 py-2 text-xs whitespace-nowrap"
                          >
                            {String(cell || '').substring(0, 50)}
                            {String(cell || '').length > 50 ? '...' : ''}
                          </td>
                        ))}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        )}
        
        {isUploading && previewData && (
          <div className="space-y-2">
            <div className="flex items-center justify-between">
              <span className="text-sm">Importing {taskType.toLowerCase()}s...</span>
              <span className="text-sm font-medium">{Math.round(uploadProgress)}%</span>
            </div>
            <Progress value={uploadProgress} className="h-2" />
          </div>
        )}
      </div>
      
      {error && (
        <Alert variant="destructive" className="mt-4">
          <AlertCircle className="h-4 w-4" />
          <AlertTitle>Error</AlertTitle>
          <AlertDescription>{error}</AlertDescription>
        </Alert>
      )}
    </div>
  );

  const renderFooter = () => (
    <div className="flex justify-end space-x-2">
      <Button
        variant="outline"
        onClick={() => setIsOpen(false)}
        disabled={isUploading}
      >
        Cancel
      </Button>
      {previewData?.preview?.length > 0 && !isUploading && (
        <Button
          onClick={handleImport}
          className="gap-2"
        >
          Import {previewData.total} {taskType.toLowerCase()}{previewData.total > 1 ? 's' : ''}
        </Button>
      )}
    </div>
  );

  return (
    <>
      <Button 
        variant="outline" 
        size="sm"
        onClick={() => setIsOpen(true)}
        className="flex items-center gap-2"
      >
        <Upload className="h-4 w-4" />
        Import {taskType}s
      </Button>

      <CustomDialog
        isOpen={isOpen}
        onClose={() => !isUploading && setIsOpen(false)}
        title={`Import ${taskType}s`}
        description={`Upload an Excel file containing ${taskType.toLowerCase()} data. Download the template for the required format.`}
        allowClose={!isUploading}
        isPending={isUploading}
      >
        <div className="flex flex-col h-[calc(100vh-260px)] max-h-[650px]">
          <div className="flex-1 overflow-hidden">
            {renderContent()}
          </div>
          <div className="pt-4 mt-4 border-t sticky bottom-0 bg-background">
            {renderFooter()}
          </div>
        </div>
      </CustomDialog>
    </>
  );
};

export default ImportTasksDialog;
