import React, { useState, useCallback, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Upload, FileText, AlertCircle, Check } from "lucide-react";
import { toast } from "@/lib/custom-toast";
import { issuesApi, employeeService, projectService, deliverablesApi } from "@/lib/api";
import * as XLSX from 'xlsx';
import { IssueCreateRequest, Employee, ProjectApi, Deliverable } 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 ImportIssuesDialogProps {
  projectId?: number;
  deliverableId?: number;
  onImportComplete: () => void;
}

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

const ImportIssuesDialog: React.FC<ImportIssuesDialogProps> = ({ 
  projectId, 
  deliverableId, 
  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 [deliverables, setDeliverables] = useState<Deliverable[]>([]);
  
  // Selected values
  const [selectedAssignedTo, setSelectedAssignedTo] = useState<number | "">("");
  const [selectedProjectId, setSelectedProjectId] = useState<number | "">(projectId || "");
  const [selectedDeliverableId, setSelectedDeliverableId] = useState<number | "">(deliverableId || "");

  // Fetch initial data
  useEffect(() => {
    const fetchInitialData = async () => {
      if (!isOpen) return;
      
      setLoading(true);
      try {
        // Fetch employees and projects in parallel
        const [employeeData, projectData] = await Promise.all([
          employeeService.getAll(),
          projectService.getAll()
        ]);
        
        setEmployees(employeeData);
        setProjects(projectData);
        
        // If projectId is provided, fetch deliverables for that project
        if (projectId) {
          try {
            const deliverablesData = await deliverablesApi.getByProjectId(projectId);
            setDeliverables(deliverablesData);
            
            // Set default selected values from props
            setSelectedProjectId(projectId);
            if (deliverableId) {
              setSelectedDeliverableId(deliverableId);
            }
          } catch (error) {
            console.error("Error fetching deliverables:", error);
          }
        }
      } catch (error) {
        console.error("Error fetching data:", error);
        toast.error("Failed to load data");
      } finally {
        setLoading(false);
      }
    };
    
    fetchInitialData();
  }, [isOpen, projectId, deliverableId]);
  
  // Fetch deliverables when project selection changes
  useEffect(() => {
    const fetchDeliverables = async () => {
      if (!selectedProjectId || typeof selectedProjectId !== 'number') {
        setDeliverables([]);
        setSelectedDeliverableId("");
        return;
      }
      
      setLoading(true);
      try {
        const deliverablesData = await deliverablesApi.getByProjectId(selectedProjectId);
        setDeliverables(deliverablesData);
      } catch (error) {
        console.error("Error fetching deliverables:", error);
        toast.error("Failed to load deliverables");
        setDeliverables([]);
      } finally {
        setLoading(false);
      }
    };
    
    fetchDeliverables();
  }, [selectedProjectId]);

  // Template Excel download handler
  const handleDownloadTemplate = () => {
    const headers = [
      "Title", 
      "Type", 
      "Priority", 
      "Severity", 
      "Description", 
      "Estimated Hours", 
      "Reported By (Optional)", 
      "Assigned To (Optional)", 
      "Project ID (Optional)", 
      "Deliverable ID (Optional)"
    ];
    
    const sampleData = [
      [
        "Sample Issue Title",
        "Feature", // Type: Bug, User Story, Task, Documentation, Enhancement
        "Low", // Priority: Low, Medium, High, Critical
        "Low", // Severity: Critical, Major, Minor, Trivial
        "Description of the issue",
        "8", // Estimated Hours
        "", // Reported By (Employee ID) - Optional
        "", // Assigned To (Employee ID) - Optional
        projectId || "", // Project ID - Optional
        deliverableId || "" // Deliverable ID - Optional
      ]
    ];
    
    // Create workbook and worksheet
    const workbook = XLSX.utils.book_new();
    const worksheet = XLSX.utils.aoa_to_sheet([headers, ...sampleData]);
    
    // Add worksheet to workbook
    XLSX.utils.book_append_sheet(workbook, worksheet, "Issues");
    
    // Write to buffer
    const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
    
    // Create blob and download
    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', 'issues_import_template.xlsx');
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

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

    // Validate file type
    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;
    }

    // Validate file size (max 10MB)
    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);
    
    // Show loading indicator
    setIsUploading(true);

    try {
      // Read the Excel file
      const reader = new FileReader();
      reader.onload = (e) => {
        try {
          const data = new Uint8Array(e.target?.result as ArrayBuffer);
          const workbook = XLSX.read(data, { type: 'array' });
          
          // Get first sheet
          const firstSheetName = workbook.SheetNames[0];
          const worksheet = workbook.Sheets[firstSheetName];
          
          // Convert to JSON
          const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
          
          // Check if there's data
          if (jsonData.length <= 1) { // Just headers or empty
            setError("The Excel file contains no data rows.");
            setIsUploading(false);
            return;
          }
          
          // Get headers from first row
          const headers = jsonData[0] as string[];
          
          // Convert to array of objects
          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);
          }
          
          // Validate column headers
          const requiredFields = ["Title", "Type", "Priority", "Description"];
          const missingFields = requiredFields.filter(field => 
            !headers.includes(field)
          );

          if (missingFields.length > 0) {
            setError(`Missing required columns: ${missingFields.join(', ')}`);
            setIsUploading(false);
            return;
          }
          
          // Store all rows for processing, but only display first 10 in preview
          const allRows = [...rows];
          const previewRows = rows.slice(0, 10);
          
          // Set data for preview
          setPreviewData({
            preview: previewRows,
            total: allRows.length,
            all: allRows
          });
          
          // Auto-start import if data is valid
          toast.success(`Excel file loaded with ${allRows.length} issues 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);
    }
  }, []);

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

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

    try {
      // Get all rows from the stored data
      const allIssues = previewData.all;
      
      const progressStep = 80 / allIssues.length;
      let successCount = 0;
      let failureCount = 0;
      
      // Process issues one by one
      for (let i = 0; i < allIssues.length; i++) {
        const issueData = allIssues[i] as Record<string, any>;
        try {
          // Map Excel fields to issue create request
          const issueRequest: IssueCreateRequest = {
            biCode: `${new Date().getTime()}-${i}`, // Generate a unique code
            type: issueData.Type || "Task",
            description: issueData.Description || "",
            estimates: String(issueData["Estimated Hours"] || "0"),
            esUnit: 1, // Default unit (hours)
            priority: issueData.Priority || "Medium",
            severity: issueData.Severity || "Minor",
            // Use inline settings if they exist, otherwise use data from excel or default to 0
            reportedBy: parseInt(String(issueData["Reported By (Optional)"])) || 0,
            assignedTo: selectedAssignedTo || parseInt(String(issueData["Assigned To (Optional)"])) || 0,
            remainingHr: parseFloat(String(issueData["Estimated Hours"])) || 0,
            title: issueData.Title,
            projectId: selectedProjectId || parseInt(String(issueData["Project ID (Optional)"])) || projectId || 0,
            deliverablesId: selectedDeliverableId || parseInt(String(issueData["Deliverable ID (Optional)"])) || deliverableId || 0
          };
          
          // Skip if missing essential data
          if (!issueRequest.title) {
            failureCount++;
            continue;
          }
          
          await issuesApi.create(issueRequest);
          successCount++;
        } catch (error) {
          console.error('Error importing issue:', error);
          failureCount++;
        }
        
        // Update progress
        setUploadProgress(10 + (i + 1) * progressStep);
      }
      
      setUploadProgress(100);
      
      if (successCount > 0) {
        toast.success(`Successfully imported ${successCount} issues`);
        
        if (failureCount > 0) {
          toast.error(`Failed to import ${failureCount} issues`);
        }
        
        setTimeout(() => {
          setIsOpen(false);
          onImportComplete();
          setPreviewData(null);
          setFileName("");
          setUploadProgress(0);
          // Reset inline settings
          setSelectedAssignedTo("");
          setSelectedProjectId("");
          setSelectedDeliverableId("");
        }, 1500);
      } else {
        throw new Error("Failed to import any issues");
      }
    } 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, deliverableId, onImportComplete, selectedAssignedTo, selectedProjectId, selectedDeliverableId]);

  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"
          >
            <FileText 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} issues
            </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="issue-excel-upload"
              disabled={isUploading}
            />
            <label
              htmlFor="issue-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 && (
          <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("issue-excel-upload") as HTMLInputElement;
                    if (input) input.value = "";
                  }}
                >
                  Change
                </Button>
              )}
            </div>
            
            {/* Inline settings for all issues */}
            <div className="border rounded-md p-4 bg-muted/20">
              <h4 className="text-sm font-medium mb-3">Set values for all issues:</h4>
              <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
                {/* Assigned To */}
                <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>
                
                {/* Project ID */}
                <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) : "");
                      if (!value) {
                        setSelectedDeliverableId("");
                      }
                    }}
                    placeholder="Select Project"
                    disabled={isUploading || loading}
                    className="w-full"
                  />
                </div>
                
                {/* Deliverable ID */}
                <div>
                  <label className="text-xs font-medium text-muted-foreground mb-1 block">
                    Deliverable
                  </label>
                  <Dropdown
                    options={[
                      { label: "— Select Deliverable —", value: "" },
                      ...deliverables.map(del => ({
                        label: del.name,
                        value: del.id.toString()
                      }))
                    ]}
                    value={selectedDeliverableId ? selectedDeliverableId.toString() : ""}
                    onValueChange={(value) => setSelectedDeliverableId(value ? parseInt(value) : "")}
                    placeholder="Select Deliverable"
                    disabled={!selectedProjectId || isUploading || loading}
                    className="w-full"
                  />
                </div>
              </div>
              <p className="text-xs text-muted-foreground mt-2">
                These values will override any values in the imported file for all issues.
              </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={() => {
                    // Reset file input to allow uploading more data
                    setFileName("");
                    setPreviewData(null);
                    const input = document.getElementById("issue-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 && (
          <div className="space-y-2">
            <div className="flex items-center justify-between">
              <span className="text-sm">Importing issues...</span>
              <span className="text-sm font-medium">{Math.round(uploadProgress)}%</span>
            </div>
            <Progress value={uploadProgress} className="h-2" />
          </div>
        )}
      </div>
      
      {error && (
        <Alert variant="destructive">
          <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} issues
        </Button>
      )}
    </div>
  );

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

      <CustomDialog
        isOpen={isOpen}
        onClose={() => !isUploading && setIsOpen(false)}
        title="Import Features"
        description="Upload an Excel file containing issue 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 ImportIssuesDialog; 