
import React, { useState, useEffect } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Label } from '@/components/ui/label';
import { useToast } from '@/hooks/use-toast';
import { supabase } from '@/integrations/supabase/client';
import * as XLSX from 'xlsx';
import { Upload, AlertCircle, FileSpreadsheet, Loader2, Check } from 'lucide-react';
import { cn } from '@/lib/utils';

const REQUIRED_FIELDS = [
  { key: 'account_number', label: 'Account Number', required: true },
  { key: 'owner_name', label: 'Owners (Name)', required: true },
  { key: 'property_address', label: 'Property Address', required: true },
];

const OPTIONAL_FIELDS = [
  { key: 'unit_id', label: 'Unit ID', required: false },
  { key: 'client_name', label: 'Client (Association)', required: false },
  { key: 'mailing_address', label: 'Mailing Address', required: false },
  { key: 'alternate_address_1', label: 'Alternate Address 1', required: false },
  { key: 'alternate_address_2', label: 'Alternate Address 2', required: false },
  { key: 'mail_format_1', label: 'Mail Format 1', required: false },
  { key: 'mail_format_2', label: 'Mail Format 2', required: false },
  { key: 'mail_format_3', label: 'Mail Format 3', required: false },
  { key: 'mail_format_4', label: 'Mail Format 4', required: false },
  { key: 'email', label: 'Email', required: false },
  { key: 'phone', label: 'Phone', required: false },
  { key: 'balance', label: 'Balance', required: false },
];

const ALL_FIELDS = [...REQUIRED_FIELDS, ...OPTIONAL_FIELDS];

export default function RosterImportDialog({ open, onOpenChange, clientId, onSuccess }) {
  const { toast } = useToast();
  const [step, setStep] = useState(1);
  const [file, setFile] = useState(null);
  const [headers, setHeaders] = useState([]);
  const [parsedData, setParsedData] = useState([]);
  const [mapping, setMapping] = useState({});
  const [loading, setLoading] = useState(false);
  const [importStats, setImportStats] = useState(null);

  useEffect(() => {
    if (open) { setStep(1); setFile(null); setHeaders([]); setParsedData([]); setMapping({}); setImportStats(null); }
  }, [open]);

  const handleFileChange = (e) => {
    const selectedFile = e.target.files[0];
    if (selectedFile) { setFile(selectedFile); parseFile(selectedFile); }
  };

  const parseFile = (file) => {
    setLoading(true);
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const data = new Uint8Array(e.target.result);
        const workbook = XLSX.read(data, { type: 'array' });
        const sheetName = workbook.SheetNames[0];
        const worksheet = workbook.Sheets[sheetName];
        const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
        if (jsonData.length < 2) throw new Error("File appears empty or missing headers");

        const fileHeaders = jsonData[0].map(h => String(h).trim());
        const rows = jsonData.slice(1);
        setHeaders(fileHeaders);
        setParsedData(rows);

        const newMapping = {};
        ALL_FIELDS.forEach(field => {
          let match = fileHeaders.find(h => h.toLowerCase() === field.label.toLowerCase());
          if (!match) match = fileHeaders.find(h => h.toLowerCase() === field.key.toLowerCase().replace(/_/g, ' '));
          if (!match) {
            if (field.key === 'owner_name' && fileHeaders.includes('Owner')) match = 'Owner';
            if (field.key === 'owner_name' && (fileHeaders.includes('Name') || fileHeaders.includes('Owner Name'))) match = fileHeaders.includes('Owner Name') ? 'Owner Name' : 'Name';
            if (field.key === 'account_number' && (fileHeaders.includes('Account') || fileHeaders.includes('Account Number'))) match = fileHeaders.includes('Account Number') ? 'Account Number' : 'Account';
            if (field.key === 'property_address' && fileHeaders.includes('Address')) match = 'Address';
            if (field.key === 'client_name' && fileHeaders.includes('Client')) match = 'Client';
            if (field.key === 'unit_id' && (fileHeaders.includes('Unit') || fileHeaders.includes('Unit ID') || fileHeaders.includes('Unit Number'))) match = fileHeaders.find(h => ['Unit ID', 'Unit Number', 'Unit'].includes(h));
            if (field.key === 'mailing_address' && fileHeaders.includes('Mailing Address')) match = 'Mailing Address';
            if (field.key === 'alternate_address_1' && fileHeaders.includes('Alternate Address 1')) match = 'Alternate Address 1';
            if (field.key === 'alternate_address_2' && fileHeaders.includes('Alternate Address 2')) match = 'Alternate Address 2';
          }
          if (match) newMapping[field.key] = match;
        });
        setMapping(newMapping);
        setStep(2);
      } catch (error) {
        console.error(error);
        toast({ variant: "destructive", title: "Error parsing file", description: error.message });
      } finally { setLoading(false); }
    };
    reader.readAsArrayBuffer(file);
  };

  const handleMappingChange = (fieldKey, header) => setMapping(prev => ({ ...prev, [fieldKey]: header }));

  const processImport = async () => {
    if (!clientId) { toast({ variant: "destructive", title: "Error", description: "No association selected." }); return; }
    const missingRequired = REQUIRED_FIELDS.filter(f => f.required && !mapping[f.key]);
    if (missingRequired.length > 0) {
      toast({ variant: "destructive", title: "Missing Mappings", description: `Please map: ${missingRequired.map(f => f.label).join(', ')}` });
      return;
    }

    setLoading(true);
    try {
      const ownersToUpsert = [];
      let skippedCount = 0;
      const headerMap = headers.reduce((acc, h, i) => { acc[h] = i; return acc; }, {});

      for (const row of parsedData) {
        const getValue = (key) => {
          const header = mapping[key];
          if (!header) return null;
          const index = headerMap[header];
          return row[index];
        };
        const accountNo = getValue('account_number');
        const ownerName = getValue('owner_name');
        const propAddress = getValue('property_address');
        if (!accountNo && !ownerName && !propAddress) { skippedCount++; continue; }
        if (!propAddress) { skippedCount++; continue; }

        // Direct mailing address takes priority; fallback to mail_format fields
        const directMailing = getValue('mailing_address');
        const mailFormats = [getValue('mail_format_1'), getValue('mail_format_2'), getValue('mail_format_3'), getValue('mail_format_4')]
          .filter(val => val && String(val).trim().length > 0);
        const mailingAddress = directMailing ? String(directMailing) : (mailFormats.length > 0 ? mailFormats.join('\n') : '');

        // Split owner name into first/last
        const fullName = String(ownerName || 'Unknown').trim();
        const nameParts = fullName.split(/\s+/);
        const firstName = nameParts[0] || 'Unknown';
        const lastName = nameParts.length > 1 ? nameParts.slice(1).join(' ') : '';

        ownersToUpsert.push({
          association_id: clientId, account_number: String(accountNo || ''),
          first_name: firstName, last_name: lastName, property_address: String(propAddress),
          mailing_address: mailingAddress,
          alternate_address_1: getValue('alternate_address_1') ? String(getValue('alternate_address_1')) : '',
          alternate_address_2: getValue('alternate_address_2') ? String(getValue('alternate_address_2')) : '',
          email: getValue('email') || '',
          phone: getValue('phone') || '', balance: parseFloat(getValue('balance') || 0)
        });
      }

      if (ownersToUpsert.length === 0) throw new Error("No valid records found to import.");

      const { error } = await supabase.from('owners').upsert(ownersToUpsert, { onConflict: 'association_id, first_name, last_name, property_address' });
      if (error) throw error;

      setImportStats({ total: parsedData.length, imported: ownersToUpsert.length, skipped: skippedCount });
      setStep(3);
      if (onSuccess) onSuccess();
    } catch (error) {
      console.error("Import failed:", error);
      if (error.code === '23505') {
        toast({ variant: "destructive", title: "Duplicate Constraint Violation", description: "Some records duplicate existing entries." });
      } else {
        toast({ variant: "destructive", title: "Import Failed", description: error.message });
      }
    } finally { setLoading(false); }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-3xl max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Import Owner Roster</DialogTitle>
          <DialogDescription>Upload a CSV or Excel file to import property owners.</DialogDescription>
        </DialogHeader>

        {step === 1 && (
          <div className="py-8 flex flex-col items-center justify-center border-2 border-dashed border-border rounded-lg bg-muted/50">
            <FileSpreadsheet className="w-12 h-12 text-muted-foreground mb-4" />
            <Label htmlFor="file-upload" className="cursor-pointer bg-primary text-primary-foreground px-4 py-2 rounded-md transition-colors flex items-center hover:bg-primary/90">
              {loading ? <Loader2 className="w-4 h-4 animate-spin mr-2" /> : <Upload className="w-4 h-4 mr-2" />}
              Select File
            </Label>
            <input id="file-upload" type="file" accept=".csv, .xlsx, .xls" className="hidden" onChange={handleFileChange} disabled={loading} />
            <p className="text-sm text-muted-foreground mt-2">Supports .csv, .xlsx</p>
          </div>
        )}

        {step === 2 && (
          <div className="space-y-6">
            <div className="bg-background p-4 rounded border">
              <h3 className="font-medium mb-4 flex items-center gap-2">
                <AlertCircle className="w-4 h-4 text-primary" /> Map CSV Columns
              </h3>
              <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                {ALL_FIELDS.map((field) => (
                  <div key={field.key} className="space-y-1">
                    <Label className={cn("text-xs font-semibold uppercase", field.required ? "text-primary" : "text-muted-foreground")}>
                      {field.label} {field.required && '*'}
                    </Label>
                    <Select value={mapping[field.key] || "ignore"} onValueChange={(val) => handleMappingChange(field.key, val === "ignore" ? null : val)}>
                      <SelectTrigger className="h-9"><SelectValue placeholder="Select Column" /></SelectTrigger>
                      <SelectContent>
                        <SelectItem value="ignore" className="text-muted-foreground font-mono text-xs italic">-- Ignore --</SelectItem>
                        {headers.map(h => (<SelectItem key={h} value={h}>{h}</SelectItem>))}
                      </SelectContent>
                    </Select>
                  </div>
                ))}
              </div>
            </div>
            <div className="bg-primary/5 p-3 rounded text-xs border border-primary/10 space-y-1">
              <p><strong>Update mode:</strong> Existing owners matched by property address will be <strong>updated</strong>, not duplicated.</p>
              <p><strong>Tip:</strong> Use "Mailing Address" for a single address field, or "Mail Format 1-4" to combine multiple lines.</p>
            </div>
          </div>
        )}

        {step === 3 && importStats && (
          <div className="py-8 flex flex-col items-center justify-center space-y-4">
            <div className="w-16 h-16 bg-emerald-100 rounded-full flex items-center justify-center text-emerald-600">
              <Check className="w-8 h-8" />
            </div>
            <h3 className="text-xl font-bold">Import Complete!</h3>
            <div className="grid grid-cols-3 gap-4 text-center w-full max-w-md">
              <div className="bg-background p-3 rounded border"><div className="text-2xl font-bold">{importStats.total}</div><div className="text-xs text-muted-foreground">Total Rows</div></div>
              <div className="bg-background p-3 rounded border"><div className="text-2xl font-bold text-emerald-600">{importStats.imported}</div><div className="text-xs text-muted-foreground">Imported</div></div>
              <div className="bg-background p-3 rounded border"><div className="text-2xl font-bold text-amber-500">{importStats.skipped}</div><div className="text-xs text-muted-foreground">Skipped</div></div>
            </div>
          </div>
        )}

        <DialogFooter className="flex justify-between sm:justify-end gap-2">
          {step === 2 && (<Button variant="outline" onClick={() => setStep(1)} disabled={loading}>Back</Button>)}
          {step < 3 && (
            <Button onClick={processImport} disabled={step === 1 || loading}>
              {loading && <Loader2 className="w-4 h-4 animate-spin mr-2" />}
              {step === 1 ? 'Next' : 'Run Import'}
            </Button>
          )}
          {step === 3 && (<Button onClick={() => onOpenChange(false)}>Close</Button>)}
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
