import React, { useState, useEffect } from 'react';
import { logViolationCreated, logViolationUpdated, logStatusChange, logStageChange } from '@/lib/violationTimelineLogger';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { supabase } from '@/integrations/supabase/client';
import { toast } from 'sonner';
import { useAuth } from '@/contexts/AuthContext';
import { Combobox } from '@/components/Combobox';
import { PropertySelect } from '@/components/PropertySelect';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { calculateNextNoticeLevel, getNoticeColor, isValidStatus, VALID_STATUSES } from '@/lib/ViolationNoticeProgressionHelper';
import { Badge } from '@/components/ui/badge';
import { Loader2, Crop, BookOpen, X, Tag } from 'lucide-react';

function ViolationDialog({ open, onOpenChange, violation, onSuccess, associationId }) {
  const { user } = useAuth();
  const [associations, setAssociations] = useState([]);
  const [assocOptions, setAssocOptions] = useState([]);
  const [calculatingLevel, setCalculatingLevel] = useState(false);
  const [processingImage, setProcessingImage] = useState(false);
  
  const [definedTypes, setDefinedTypes] = useState([]);
  const [selectedDefinedType, setSelectedDefinedType] = useState("");
  
  const [formData, setFormData] = useState({
    association_id: '',
    property_id: '',
    unit_id: '',
    address: '',
    violation_type: '',
    article_section: '',
    citation: '',
    requested_action: '',
    notes: '',
    violation_date: '',
    due_date: '',
    stage: 'First Notice',
    priority: 'medium',
    status: 'open'
  });
  const [photoFile, setPhotoFile] = useState(null);
  const [loading, setLoading] = useState(false);
  const [selectedTags, setSelectedTags] = useState([]);

  const defaultViolationTypeOptions = [
    'Parking Violation', 'Noise Complaint', 'Trash Disposal Issue',
    'Unkempt Property', 'Landscaping Non-compliance',
    'Structural Alteration Without Approval', 'Other'
  ];

  const STAGE_OPTIONS = ["First Notice", "Second Notice", "Third & Final Notice"];

  const formatDateForInput = (date) => {
    if (!date) return '';
    if (typeof date === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(date)) return date;
    const d = new Date(date);
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    return `${y}-${m}-${day}`;
  };

  useEffect(() => {
    const fetchAssociations = async () => {
      const { data, error } = await supabase.from('associations').select('id, name').eq('status', 'active').order('name');
      if (!error) {
        setAssociations(data);
        setAssocOptions(data.map(c => ({ value: c.id, label: c.name })));
      }
    };
    if (open) fetchAssociations();
  }, [open]);

  useEffect(() => {
    const fetchDefinedTypes = async () => {
      if (!formData.association_id) { setDefinedTypes([]); return; }
      const { data, error } = await supabase.from('violation_types').select('*').eq('association_id', formData.association_id).order('category');
      if (!error) setDefinedTypes(data || []);
    };
    fetchDefinedTypes();
  }, [formData.association_id]);

  useEffect(() => {
    if (violation) {
      let latestHistory = {};
      if (violation.notice_history && Array.isArray(violation.notice_history) && violation.notice_history.length > 0) {
          latestHistory = violation.notice_history[violation.notice_history.length - 1] || {};
      }
      setFormData({
        association_id: violation.association_id || '',
        property_id: violation.owner_id || '',
        unit_id: violation.unit_id || '',
        address: violation.address || '',
        violation_type: violation.violation_type || '',
        article_section: latestHistory.article_section || '',
        citation: latestHistory.citation || '',
        requested_action: violation.description || latestHistory.requested_action || '',
        notes: violation.notes || '',
        violation_date: formatDateForInput(violation.violation_date),
        due_date: formatDateForInput(violation.due_date),
        stage: violation.stage || violation.notice_level || 'First Notice',
        priority: violation.priority || 'medium',
        status: violation.status || 'open',
        certified_mail: violation.certified_mail || '',
      });
      setSelectedTags(violation.tags || []);
      setPhotoFile(null);
    } else {
      setFormData({
        association_id: associationId || '',
        property_id: '', unit_id: '', address: '', violation_type: '',
        article_section: '', citation: '', requested_action: '',
        notes: '', violation_date: formatDateForInput(new Date()),
        due_date: '', stage: 'First Notice', priority: 'medium', status: 'open',
        certified_mail: '',
      });
      setSelectedTags([]);
      setPhotoFile(null);
    }
    if (!violation && open) {
      const params = new URLSearchParams(window.location.search);
      const associationIdParam = params.get('associationId');
      const ownerIdParam = params.get('ownerId');
      if (associationIdParam || ownerIdParam) {
        setFormData(prev => ({
          ...prev,
          association_id: associationIdParam || prev.association_id,
          property_id: ownerIdParam || prev.property_id,
        }));
      }
    }
    setSelectedDefinedType("");
  }, [violation, open, associationId]);

  useEffect(() => {
    const updateLevel = async () => {
      if (!violation && formData.property_id) {
        setCalculatingLevel(true);
        const level = await calculateNextNoticeLevel(formData.property_id);
        setFormData(prev => ({ ...prev, stage: level }));
        setCalculatingLevel(false);
      }
    };
    updateLevel();
  }, [formData.property_id, violation]);

  const handleDefinedTypeChange = (typeId) => {
    const selected = definedTypes.find(t => t.id === typeId);
    if (selected) {
      setFormData(prev => ({
        ...prev,
        violation_type: selected.category || prev.violation_type,
        article_section: selected.article_section || prev.article_section,
        citation: selected.citation || prev.citation,
        requested_action: selected.requested_action || prev.requested_action
      }));
      setSelectedDefinedType(typeId);
    }
  };

  const processImage = (file) => {
    return new Promise((resolve) => {
      if (!file.type.startsWith('image/')) { resolve(file); return; }
      const img = new Image();
      const url = URL.createObjectURL(file);
      img.src = url;
      img.onload = () => {
        URL.revokeObjectURL(url);
        const { width, height } = img;
        if (height > width) {
          try {
            const canvas = document.createElement('canvas');
            const size = width;
            canvas.width = size;
            canvas.height = size;
            const ctx = canvas.getContext('2d');
            const yOffset = (height - width) / 2;
            ctx.drawImage(img, 0, yOffset, width, width, 0, 0, size, size);
            canvas.toBlob((blob) => {
              if (blob) {
                resolve(new File([blob], file.name, { type: file.type, lastModified: Date.now() }));
              } else { resolve(file); }
            }, file.type, 0.9);
          } catch (e) {
            console.error("Image processing failed", e);
            resolve(file);
          }
        } else { resolve(file); }
      };
      img.onerror = () => { URL.revokeObjectURL(url); resolve(file); };
    });
  };

  const handleFileChange = async (e) => {
    const file = e.target.files[0];
    if (!file) return;
    const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
    if (!allowedTypes.includes(file.type)) {
      toast.error('Please upload a valid image file (JPEG, PNG, GIF, or WebP).');
      return;
    }
    setProcessingImage(true);
    try {
      const processedFile = await processImage(file);
      setPhotoFile(processedFile);
      if (processedFile !== file) {
        toast.success('Portrait image was automatically cropped to square format.');
      }
    } catch (err) {
      console.error("Error processing image:", err);
      setPhotoFile(file);
    } finally {
      setProcessingImage(false);
    }
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!formData.association_id) {
      toast.error('Please select an Association.');
      return;
    }
    if (!formData.property_id && !formData.address) {
      toast.error('Please select a Property or enter an address.');
      return;
    }
    if (!isValidStatus(formData.status)) {
      toast.error(`Status '${formData.status}' is not valid. Allowed: ${VALID_STATUSES.join(', ')}`);
      return;
    }

    setLoading(true);
    try {
      let photo_url = violation?.photo_url || null;
      if (photoFile) {
        const fileExtension = photoFile.name.split('.').pop();
        const fileName = `${crypto.randomUUID()}.${fileExtension}`;
        const { data: uploadData, error: uploadError } = await supabase.storage.from('violation-photos').upload(fileName, photoFile);
        if (uploadError) throw uploadError;
        const { data: urlData } = supabase.storage.from('violation-photos').getPublicUrl(uploadData.path);
        photo_url = urlData.publicUrl;
      }

      const timestamp = new Date().toISOString();
      const newHistoryEntry = {
        date: timestamp, status: formData.status, notice_level: formData.stage,
        violation_type: formData.violation_type, article_section: formData.article_section,
        citation: formData.citation, requested_action: formData.requested_action,
        notes: formData.notes, action: violation ? 'Violation Updated' : 'Violation Created'
      };

      let updatedHistory = [];
      if (violation && violation.notice_history && Array.isArray(violation.notice_history)) {
        updatedHistory = [...violation.notice_history, newHistoryEntry];
      } else {
        updatedHistory = [newHistoryEntry];
      }

      const dataToSubmit = { 
        association_id: formData.association_id,
        owner_id: formData.property_id && formData.property_id.length > 0 ? formData.property_id : null,
        unit_id: formData.unit_id && formData.unit_id.length > 0 ? formData.unit_id : null,
        address: formData.address,
        title: formData.violation_type || 'Violation',
        violation_type: formData.violation_type,
        status: formData.status,
        priority: formData.priority,
        stage: formData.stage,
        notice_level: formData.stage,
        violation_date: formData.violation_date || null,
        due_date: formData.due_date || null,
        notes: formData.notes,
        description: formData.requested_action,
        photo_url,
        notice_history: updatedHistory,
        tags: selectedTags
      };

      if (formData.certified_mail !== undefined) {
        dataToSubmit.certified_mail = formData.certified_mail?.trim() || null;
      }

      if (!violation) dataToSubmit.created_by = user?.id;

      const { data: insertResult, error } = violation
        ? await supabase.from('violations').update(dataToSubmit).eq('id', violation.id).select('id').maybeSingle()
        : await supabase.from('violations').insert([dataToSubmit]).select('id').single();

      if (error) throw error;

      // ── Auto-log timeline entries ──
      const targetId = violation?.id || insertResult?.id;
      if (targetId) {
        if (!violation) {
          // New violation created
          await logViolationCreated(targetId, {
            address: formData.address,
            violationType: formData.violation_type,
            noticeLevel: formData.stage,
          });
        } else {
          // Existing violation updated — log specific changes
          const changes = {};
          if (violation.status !== formData.status) {
            changes.status = { from: violation.status, to: formData.status };
            await logStatusChange(targetId, violation.status, formData.status);
          }
          if ((violation.stage || violation.notice_level) !== formData.stage) {
            const prevStage = violation.stage || violation.notice_level;
            changes.stage = { from: prevStage, to: formData.stage };
            await logStageChange(targetId, prevStage, formData.stage);
          }
          if (violation.priority !== formData.priority) {
            changes.priority = { from: violation.priority, to: formData.priority };
          }
          if (violation.violation_type !== formData.violation_type) {
            changes.violation_type = { from: violation.violation_type, to: formData.violation_type };
          }
          if ((violation.address || '') !== (formData.address || '')) {
            changes.address = { from: violation.address, to: formData.address };
          }
          if ((violation.notes || '') !== (formData.notes || '')) {
            changes.notes = { from: violation.notes, to: formData.notes };
          }
          if ((violation.violation_date || '') !== (formData.violation_date || '')) {
            changes.violation_date = { from: violation.violation_date, to: formData.violation_date };
          }
          if ((violation.due_date || '') !== (formData.due_date || '')) {
            changes.due_date = { from: violation.due_date, to: formData.due_date };
          }
          if ((violation.description || '') !== (formData.requested_action || '')) {
            changes.requested_action = { from: violation.description, to: formData.requested_action };
          }
          if ((violation.article_section || '') !== (formData.article_section || '')) {
            changes.article_section = { from: violation.article_section, to: formData.article_section };
          }
          if ((violation.citation || '') !== (formData.citation || '')) {
            changes.citation = { from: violation.citation, to: formData.citation };
          }
          if (Object.keys(changes).length > 0) {
            await logViolationUpdated(targetId, changes);
          }
        }
      }

      // Send in-app notifications
      try {
        const isEscalated = formData.status === 'escalated' || (violation && violation.status !== 'escalated' && formData.status === 'escalated');
        const notifTitle = isEscalated
          ? `⚠️ Violation Escalated: ${formData.violation_type || 'Violation'}`
          : violation
          ? `Violation Updated: ${formData.violation_type || 'Violation'}`
          : `New Violation: ${formData.violation_type || 'Violation'}`;
        const notifMessage = `${formData.address ? formData.address + ' — ' : ''}Status: ${formData.status}, Stage: ${formData.stage}`;

        const { data: staffRoles } = await supabase
          .from('user_roles')
          .select('user_id')
          .in('role', ['admin', 'manager']);

        if (staffRoles && staffRoles.length > 0) {
          const notifications = staffRoles
            .filter(r => r.user_id !== user?.id)
            .map(r => ({
              user_id: r.user_id,
              type: isEscalated ? 'warning' : 'info',
              title: notifTitle,
              message: notifMessage,
              related_item_type: 'violation',
            }));
          if (notifications.length > 0) {
            await supabase.from('in_app_notifications').insert(notifications);
          }
        }
      } catch (notifErr) {
        console.error('Failed to send violation notification:', notifErr);
      }

      toast.success(`Violation ${violation ? 'updated' : 'created'} successfully.`);
      onSuccess();
      onOpenChange(false);
    } catch (error) {
      console.error(error);
      toast.error(error.message);
    } finally {
      setLoading(false);
    }
  };

  // Only allow selection from the association's defined violation types
  const associationTypeOptions = definedTypes.map(dt => dt.category).filter(Boolean);
  const combinedTypeOptions = Array.from(new Set([...associationTypeOptions, formData.violation_type])).filter(Boolean);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[700px] bg-card max-h-[90vh] flex flex-col p-0 overflow-hidden gap-0">
        <DialogHeader className="p-6 pb-4 bg-card border-b shrink-0">
          <DialogTitle>{violation ? 'Edit Violation' : 'Log New Violation'}</DialogTitle>
          <DialogDescription>{violation ? 'Update the details for this violation.' : 'Create a new violation record.'}</DialogDescription>
        </DialogHeader>

        <div className="flex-1 overflow-y-auto p-6">
            <form id="violation-form" onSubmit={handleSubmit} className="space-y-4">
              <div className="grid grid-cols-2 gap-4">
                 <div>
                    <Label>Association *</Label>
                    <div className="mt-1">
                        <Combobox options={assocOptions} value={formData.association_id} onChange={(value) => setFormData({ ...formData, association_id: value, property_id: '', unit_id: '', address: '' })} placeholder="Select association..." className="bg-card" />
                    </div>
                 </div>
                 <div>
                    <Label>Status</Label>
                    <Select value={formData.status} onValueChange={(val) => setFormData({ ...formData, status: val })}>
                       <SelectTrigger className="mt-1 bg-card"><SelectValue /></SelectTrigger>
                       <SelectContent>
                          <SelectItem value="open">Open</SelectItem>
                          <SelectItem value="resolved">Resolved</SelectItem>
                          <SelectItem value="recommended_for_fining">Recommended for Fining</SelectItem>
                          <SelectItem value="fined">Fined</SelectItem>
                          <SelectItem value="escalated">Escalated</SelectItem>
                          <SelectItem value="closed">Closed</SelectItem>
                          <SelectItem value="pending">Pending</SelectItem>
                       </SelectContent>
                    </Select>
                 </div>
              </div>

              <div>
                <Label>Property / Owner *</Label>
                <div className="mt-1">
                    <PropertySelect associationId={formData.association_id} value={formData.property_id} onChange={(val) => setFormData(prev => ({ ...prev, property_id: val }))} onSelectProperty={(prop) => setFormData(prev => ({ ...prev, property_id: prop?.id, unit_id: prop?.unit_id || '', address: prop?.property_address || '' }))} className="bg-card" />
                </div>
                {formData.address && <p className="text-xs text-muted-foreground mt-1">{formData.address}</p>}
              </div>

              {definedTypes.length > 0 && (
                <div className="bg-primary/5 border border-primary/20 p-3 rounded-md">
                  <Label className="text-primary flex items-center gap-1.5 mb-1.5"><BookOpen className="w-3.5 h-3.5" /> Load Standard Violation</Label>
                  <Select value={selectedDefinedType} onValueChange={handleDefinedTypeChange}>
                     <SelectTrigger className="bg-card"><SelectValue placeholder="Select a standard violation..." /></SelectTrigger>
                     <SelectContent>
                       {definedTypes.map(dt => (<SelectItem key={dt.id} value={dt.id}>{dt.category} {dt.article_section ? `(${dt.article_section})` : ''}</SelectItem>))}
                     </SelectContent>
                  </Select>
                </div>
              )}

              <div className="bg-muted/50 p-3 rounded-lg border">
                 <div className="flex justify-between items-center mb-2">
                    <Label className="font-semibold">Violation Stage</Label>
                    {calculatingLevel && <div className="flex items-center text-xs text-primary"><Loader2 className="w-3 h-3 mr-1 animate-spin" /> Calculating...</div>}
                    {!calculatingLevel && !violation && formData.property_id && (<Badge variant="outline" className="text-[10px] font-normal bg-card">Auto-detected</Badge>)}
                 </div>
                 <Select value={formData.stage} onValueChange={(val) => setFormData({ ...formData, stage: val })}>
                    <SelectTrigger className="mt-1 bg-card"><SelectValue placeholder="Select Stage" /></SelectTrigger>
                    <SelectContent>
                       <SelectItem value="null">None</SelectItem>
                       {STAGE_OPTIONS.map(stage => (<SelectItem key={stage} value={stage}>{stage}</SelectItem>))}
                    </SelectContent>
                 </Select>
              </div>

              <div className="grid grid-cols-2 gap-4">
                 <div>
                    <Label>Priority</Label>
                    <Select value={formData.priority} onValueChange={(val) => setFormData({ ...formData, priority: val })}>
                       <SelectTrigger className="mt-1 bg-card"><SelectValue /></SelectTrigger>
                       <SelectContent>
                          <SelectItem value="low">Low</SelectItem>
                          <SelectItem value="medium">Medium</SelectItem>
                          <SelectItem value="high">High</SelectItem>
                       </SelectContent>
                    </Select>
                 </div>
                 <div>
                    <Label>Violation Date</Label>
                    <Input type="date" value={formData.violation_date} onChange={(e) => setFormData({ ...formData, violation_date: e.target.value })} className="mt-1 bg-card" />
                 </div>
              </div>

              <div className="grid grid-cols-2 gap-4">
                 <div><Label>Due Date</Label><Input type="date" value={formData.due_date} onChange={(e) => setFormData({ ...formData, due_date: e.target.value })} className="mt-1 bg-card" /></div>
                 <div>
                   <Label>Violation Type *</Label>
                   <Input
                     list="violation-types-list"
                     value={formData.violation_type}
                     onChange={(e) => setFormData({ ...formData, violation_type: e.target.value })}
                     className="mt-1 bg-card"
                     placeholder={!formData.association_id ? "Select an association first..." : (associationTypeOptions.length ? "Select a type..." : "No types defined for this association")}
                     disabled={!formData.association_id}
                     required
                   />
                   <datalist id="violation-types-list">{combinedTypeOptions.map((type, idx) => (<option key={idx} value={type} />))}</datalist>
                 </div>
              </div>

              <div>
                <Label>Certified Mail # (optional)</Label>
                <Input
                  value={formData.certified_mail || ''}
                  onChange={(e) => setFormData({ ...formData, certified_mail: e.target.value })}
                  placeholder="e.g. 9407 1234 5678 9012 3456 78"
                  className="mt-1 bg-card"
                />
              </div>

              <div className="grid grid-cols-2 gap-4">
                 <div><Label>Article / Section</Label><Input value={formData.article_section} onChange={(e) => setFormData({ ...formData, article_section: e.target.value })} placeholder="e.g. Article V" className="mt-1 bg-card" /></div>
                 <div><Label>Citation</Label><Input value={formData.citation} onChange={(e) => setFormData({ ...formData, citation: e.target.value })} placeholder="Relevant CC&R text" className="mt-1 bg-card" /></div>
              </div>

              <div><Label>Requested Action</Label><Textarea value={formData.requested_action} onChange={(e) => setFormData({ ...formData, requested_action: e.target.value })} placeholder="What needs to be done to fix this?" className="mt-1 bg-card" rows={3} /></div>

              {/* Tags */}
              <div>
                <Label className="flex items-center gap-1.5 mb-1.5"><Tag className="w-3.5 h-3.5" /> Tags</Label>
                <div className="flex flex-wrap gap-1.5 mb-2">
                  {selectedTags.map((tag, idx) => (
                    <Badge key={idx} variant="secondary" className="text-xs gap-1 pr-1">
                      {tag}
                      <button type="button" onClick={() => setSelectedTags(prev => prev.filter((_, i) => i !== idx))} className="ml-0.5 hover:text-destructive"><X className="w-3 h-3" /></button>
                    </Badge>
                  ))}
                </div>
                {definedTypes.length > 0 && (
                  <div className="flex flex-wrap gap-1.5">
                    {definedTypes.filter(dt => !selectedTags.includes(dt.category)).map(dt => (
                      <button type="button" key={dt.id} onClick={() => setSelectedTags(prev => [...prev, dt.category])} className="inline-flex items-center rounded-full border border-dashed border-muted-foreground/30 px-2.5 py-0.5 text-xs text-muted-foreground hover:bg-muted hover:text-foreground transition-colors">
                        + {dt.category}
                      </button>
                    ))}
                  </div>
                )}
                {definedTypes.length === 0 && formData.association_id && (
                  <p className="text-xs text-muted-foreground">No violation types defined for this association. Manage types from the Violations page.</p>
                )}
              </div>

              <div>
                <Label className="flex justify-between">
                    <span>Photo</span>
                    {processingImage && <span className="text-xs text-primary flex items-center"><Crop className="w-3 h-3 mr-1" /> Cropping...</span>}
                </Label>
                <input type="file" onChange={handleFileChange} disabled={processingImage} className="w-full mt-1 text-sm file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:bg-muted bg-card" />
                {photoFile && !processingImage && <p className="text-[10px] text-green-600 mt-1">Image ready for upload.</p>}
              </div>

              <div className="pb-4"><Label>Internal Notes</Label><Textarea value={formData.notes} onChange={(e) => setFormData({ ...formData, notes: e.target.value })} rows={2} className="mt-1 bg-card" /></div>
            </form>
        </div>

        <div className="p-4 bg-card border-t shrink-0 flex justify-end space-x-2">
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>Cancel</Button>
            <Button type="submit" form="violation-form" disabled={loading || calculatingLevel || processingImage}>
                {loading ? 'Saving...' : violation ? 'Update' : 'Create'}
            </Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}

export default ViolationDialog;
