import { useState, useEffect, useMemo, useRef } from "react";
import ReactQuill from "react-quill-new";
import "react-quill-new/dist/quill.snow.css";
import { supabase } from "@/integrations/supabase/client";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { formatDateTimeShortEST } from "@/lib/timezoneUtils";
import { Megaphone, Plus, Archive, Trash2, Edit2, Users, AlertCircle, RefreshCw, Pin, PinOff } from "lucide-react";
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
} from "@/components/ui/select";
import {
  Table, TableBody, TableCell, TableHead, TableHeader, TableRow,
} from "@/components/ui/table";
import { useAuth } from "@/contexts/AuthContext";
import { useToast } from "@/components/ui/use-toast";
import { htmlToPlainText } from "@/lib/htmlTextUtils";

const ALL_ASSOCIATIONS_VALUE = "__all_associations__";

interface Announcement {
  id: string;
  title: string;
  content: string;
  status: string;
  visibility: string;
  association_id: string | null;
  created_by: string | null;
  created_at: string;
  updated_at: string;
  pinned?: boolean;
  expires_at?: string | null;
}

interface Association {
  id: string;
  name: string;
}

export default function AnnouncementManager({ boardAssociationIds }: { boardAssociationIds?: string[] } = {}) {
  const { user, isAdmin, isStaff } = useAuth();
  const [announcements, setAnnouncements] = useState<Announcement[]>([]);
  const [associations, setAssociations] = useState<Association[]>([]);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [modalOpen, setModalOpen] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [formData, setFormData] = useState({ title: "", content: "", visibility: "staff_board", association_id: "", pinned: false, expires_at: "" });
  const { toast } = useToast();
  const quillRef = useRef<any>(null);

  const isBoardView = !!boardAssociationIds?.length;
  const canManage = (isAdmin || isStaff) && !isBoardView;

  useEffect(() => {
    fetchAnnouncements();
    if (canManage) fetchAssociations();
  }, []);

  // Quill image handler — uploads to announcement-images bucket, embeds public URL
  const imageHandler = () => {
    const input = document.createElement("input");
    input.setAttribute("type", "file");
    input.setAttribute("accept", "image/*");
    input.click();
    input.onchange = async () => {
      const file = input.files?.[0];
      if (!file) return;
      try {
        const ext = file.name.split(".").pop() || "png";
        const path = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}.${ext}`;
        const { error: upErr } = await supabase.storage
          .from("announcement-images")
          .upload(path, file, { contentType: file.type, upsert: false });
        if (upErr) throw upErr;
        const { data: { publicUrl } } = supabase.storage.from("announcement-images").getPublicUrl(path);
        const editor = quillRef.current?.getEditor?.();
        const range = editor?.getSelection(true);
        editor?.insertEmbed(range?.index ?? 0, "image", publicUrl, "user");
        editor?.setSelection((range?.index ?? 0) + 1, 0);
      } catch (err: any) {
        toast({ variant: "destructive", title: "Image upload failed", description: err.message });
      }
    };
  };

  const quillModules = useMemo(() => ({
    toolbar: {
      container: [
        [{ header: [1, 2, 3, false] }],
        ["bold", "italic", "underline", "strike"],
        [{ list: "ordered" }, { list: "bullet" }],
        ["link", "image"],
        ["clean"],
      ],
      handlers: { image: imageHandler },
    },
  }), []);

  const fetchAssociations = async () => {
    const { data } = await supabase.from("associations").select("id, name").order("name");
    setAssociations((data as Association[]) || []);
  };

  const fetchAnnouncements = async () => {
    setLoading(true);
    setError(null);
    try {
      const nowIso = new Date().toISOString();
      const { data, error: fetchError } = await supabase
        .from("announcements")
        .select("*")
        .eq("status", "active")
        .or(`expires_at.is.null,expires_at.gt.${nowIso}`)
        .order("pinned", { ascending: false })
        .order("created_at", { ascending: false })
        .limit(50);

      if (fetchError) throw fetchError;
      setAnnouncements((data as Announcement[]) ?? []);
    } catch (err: any) {
      console.error("Error fetching announcements:", err);
      setError("Failed to load announcements.");
    } finally {
      setLoading(false);
    }
  };

  const handleSave = async () => {
    if (!formData.title || !formData.content) {
      toast({ variant: "destructive", title: "Title and Content required" });
      return;
    }

    setSaving(true);

    try {
      const payload: any = {
        title: formData.title,
        content: formData.content,
        visibility: formData.visibility,
        association_id: formData.association_id || null,
        status: "active",
        pinned: formData.pinned,
        expires_at: formData.expires_at ? new Date(formData.expires_at).toISOString() : null,
      };

      let savedId: string | null = editingId;
      const isNew = !editingId;

      if (editingId) {
        const { error: updateError } = await supabase
          .from("announcements")
          .update({ ...payload, updated_at: new Date().toISOString() })
          .eq("id", editingId);
        if (updateError) throw updateError;
      } else {
        const { data: inserted, error: insertError } = await supabase
          .from("announcements")
          .insert([{ ...payload, created_by: user?.id }])
          .select("id")
          .single();
        if (insertError) throw insertError;
        savedId = inserted?.id ?? null;
      }

      // Send notification email for newly-posted announcements (skip community-page-only)
      if (isNew && savedId && formData.visibility !== "public_only") {
        supabase.functions
          .invoke("notify-announcement", { body: { announcement_id: savedId } })
          .then(({ error: notifyErr }) => {
            if (notifyErr) console.error("notify-announcement failed:", notifyErr);
          });
        toast({ title: "Announcement posted", description: "Email notifications are being sent." });
      } else {
        toast({ title: editingId ? "Announcement updated" : "Announcement posted" });
      }

      setModalOpen(false);
      setEditingId(null);
      setFormData({ title: "", content: "", visibility: "staff_board", association_id: "", pinned: false, expires_at: "" });
      fetchAnnouncements();
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error saving announcement", description: err.message });
    } finally {
      setSaving(false);
    }
  };

  const handleArchive = async (id: string) => {
    try {
      const { error: archiveError } = await supabase.from("announcements").update({ status: "archived" }).eq("id", id);
      if (archiveError) throw archiveError;
      fetchAnnouncements();
      toast({ title: "Announcement archived" });
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error archiving announcement", description: err.message });
    }
  };

  const handleDelete = async (id: string) => {
    try {
      const { error: deleteError } = await supabase.from("announcements").delete().eq("id", id);
      if (deleteError) throw deleteError;
      fetchAnnouncements();
      toast({ title: "Announcement deleted" });
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error deleting announcement", description: err.message });
    }
  };

  const handleTogglePin = async (id: string, current: boolean) => {
    try {
      const { error: pinErr } = await supabase
        .from("announcements")
        .update({ pinned: !current, updated_at: new Date().toISOString() })
        .eq("id", id);
      if (pinErr) throw pinErr;
      fetchAnnouncements();
      toast({ title: !current ? "Announcement pinned" : "Announcement unpinned" });
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error updating pin", description: err.message });
    }
  };

  // Convert an ISO string to the value format expected by <input type="datetime-local">
  const isoToLocalInput = (iso?: string | null) => {
    if (!iso) return "";
    const d = new Date(iso);
    if (isNaN(d.getTime())) return "";
    const pad = (n: number) => String(n).padStart(2, "0");
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
  };

  const openModal = (ann?: Announcement | null) => {
    if (ann) {
      setEditingId(ann.id);
      setFormData({ title: ann.title, content: ann.content, visibility: ann.visibility || "all", association_id: ann.association_id || "", pinned: !!ann.pinned, expires_at: isoToLocalInput(ann.expires_at) });
    } else {
      setEditingId(null);
      setFormData({ title: "", content: "", visibility: "staff_board", association_id: "", pinned: false, expires_at: "" });
    }
    setModalOpen(true);
  };

  const visibilityLabel = (v: string) => {
    switch (v) {
      case "staff_board": return "Staff & Board";
      case "all": return "Staff, Board & Homeowners";
      case "public": return "Public (Everyone)";
      case "public_only": return "Public Only";
      default: return "Staff & Board";
    }
  };

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-start justify-between">
        <div className="flex items-center gap-3">
          <Megaphone className="w-8 h-8 text-primary" />
          <div>
            <h1 className="text-2xl font-bold text-foreground">Announcements</h1>
            <p className="text-sm text-muted-foreground">Post and manage team announcements visible across the platform.</p>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <Button variant="ghost" size="icon" className="h-9 w-9" onClick={fetchAnnouncements}>
            <RefreshCw className="w-4 h-4" />
          </Button>
          {canManage && (
            <Button size="sm" onClick={() => openModal()}>
              <Plus className="w-4 h-4 mr-1.5" /> Post Announcement
            </Button>
          )}
        </div>
      </div>

      {/* Table Card */}
      <div className="bg-card border rounded-lg">
        <div className="p-5 border-b">
          <h2 className="text-lg font-semibold text-foreground">Active Announcements</h2>
          <p className="text-sm text-muted-foreground mt-1">
            All active announcements are displayed on the dashboard and visible to relevant staff.
          </p>
        </div>

        <div className="p-5">
          {loading ? (
            <div className="text-center py-8 text-muted-foreground">Loading announcements...</div>
          ) : error ? (
            <div className="text-center py-8 text-destructive">
              <AlertCircle className="w-6 h-6 mx-auto mb-2" />
              <p className="text-sm font-medium">{error}</p>
              <Button variant="outline" size="sm" onClick={fetchAnnouncements} className="mt-3">Retry</Button>
            </div>
          ) : announcements.length === 0 ? (
            <div className="text-center py-8 text-muted-foreground">No active announcements.</div>
          ) : (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Title</TableHead>
                  <TableHead>Content</TableHead>
                  <TableHead className="w-[140px]">Visibility</TableHead>
                  <TableHead className="w-[160px]">Posted</TableHead>
                  <TableHead className="w-[160px]">Expires</TableHead>
                  {canManage && <TableHead className="w-[150px] text-right">Actions</TableHead>}
                </TableRow>
              </TableHeader>
              <TableBody>
                {announcements.map((ann) => (
                  <TableRow key={ann.id}>
                    <TableCell>
                      <div className="flex items-center gap-1.5">
                        {ann.pinned && <Pin className="w-3.5 h-3.5 text-primary fill-primary" />}
                        <span className="font-semibold text-foreground">{ann.title}</span>
                      </div>
                    </TableCell>
                    <TableCell>
                      <p className="text-sm text-muted-foreground line-clamp-2 max-w-[400px]">
                        {htmlToPlainText(ann.content)}
                      </p>
                    </TableCell>
                    <TableCell>
                      <Badge variant="outline" className="text-[10px] font-medium">
                        {visibilityLabel(ann.visibility)}
                      </Badge>
                    </TableCell>
                    <TableCell className="text-sm text-muted-foreground whitespace-nowrap">
                      {formatDateTimeShortEST(ann.created_at)}
                    </TableCell>
                    <TableCell className="text-sm text-muted-foreground whitespace-nowrap">
                      {ann.expires_at ? formatDateTimeShortEST(ann.expires_at) : <span className="italic">Never</span>}
                    </TableCell>
                    {canManage && (
                      <TableCell className="text-right">
                        <div className="flex justify-end gap-1">
                          <Button
                            variant="ghost"
                            size="icon"
                            className={`h-8 w-8 ${ann.pinned ? "text-primary hover:text-primary" : "text-muted-foreground hover:text-primary"}`}
                            title={ann.pinned ? "Unpin" : "Pin to top"}
                            onClick={() => handleTogglePin(ann.id, !!ann.pinned)}
                          >
                            {ann.pinned ? <PinOff className="w-4 h-4" /> : <Pin className="w-4 h-4" />}
                          </Button>
                          <Button variant="ghost" size="icon" className="h-8 w-8 text-primary hover:text-primary" onClick={() => openModal(ann)}>
                            <Edit2 className="w-4 h-4" />
                          </Button>
                          <Button variant="ghost" size="icon" className="h-8 w-8 text-amber-600 hover:text-amber-600" title="Archive" onClick={() => handleArchive(ann.id)}>
                            <Archive className="w-4 h-4" />
                          </Button>
                          <Button variant="ghost" size="icon" className="h-8 w-8 text-destructive hover:text-destructive" title="Delete" onClick={() => handleDelete(ann.id)}>
                            <Trash2 className="w-4 h-4" />
                          </Button>
                        </div>
                      </TableCell>
                    )}
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          )}
        </div>
      </div>

      {/* Modal */}
      <Dialog open={modalOpen} onOpenChange={setModalOpen}>
        <DialogContent className="sm:max-w-[700px] max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>{editingId ? "Edit Announcement" : "Post Announcement"}</DialogTitle>
          </DialogHeader>
          <div className="grid gap-4 py-4">
            <div className="space-y-2">
              <Label>Title</Label>
              <Input
                value={formData.title}
                onChange={(e) => setFormData({ ...formData, title: e.target.value })}
                placeholder="Announcement title..."
              />
            </div>
            <label className="flex items-center gap-2 text-sm cursor-pointer select-none">
              <input
                type="checkbox"
                checked={formData.pinned}
                onChange={(e) => setFormData({ ...formData, pinned: e.target.checked })}
                className="h-4 w-4 rounded border-input accent-primary"
              />
              <Pin className="w-3.5 h-3.5 text-primary" />
              <span className="font-medium text-foreground">Pin to top</span>
              <span className="text-xs text-muted-foreground">— Pinned announcements appear above all others.</span>
            </label>
            <div className="space-y-2">
              <Label>Content</Label>
              <div className="rounded-md border bg-background">
                <ReactQuill
                  ref={quillRef}
                  theme="snow"
                  value={formData.content}
                  onChange={(val) => setFormData({ ...formData, content: val })}
                  modules={quillModules}
                  placeholder="Write your announcement... use the image button to embed pictures."
                  className="announcement-quill"
                />
              </div>
              <p className="text-xs text-muted-foreground">Click the image icon in the toolbar to upload and embed an image.</p>
            </div>
            <div className="space-y-2">
              <Label>Visibility</Label>
              <Select value={formData.visibility} onValueChange={(val) => setFormData({ ...formData, visibility: val })}>
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="staff_board">Staff & Board Members</SelectItem>
                  <SelectItem value="all">Staff, Board Members & Homeowners</SelectItem>
                  <SelectItem value="public">Public (Everyone incl. Community Page)</SelectItem>
                  <SelectItem value="public_only">Public Only (Community Page only)</SelectItem>
                </SelectContent>
              </Select>
              {formData.visibility === "public" && (
                <p className="text-xs text-amber-600">Public announcements appear on the community page when the Announcements module is enabled.</p>
              )}
            </div>
            <div className="space-y-2">
              <Label>Association</Label>
              <Select
                value={formData.association_id || ALL_ASSOCIATIONS_VALUE}
                onValueChange={(val) => setFormData({ ...formData, association_id: val === ALL_ASSOCIATIONS_VALUE ? "" : val })}
              >
                <SelectTrigger>
                  <SelectValue placeholder="Select association (optional)" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={ALL_ASSOCIATIONS_VALUE}>All / No Association</SelectItem>
                  {associations.map(a => (
                    <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <p className="text-xs text-muted-foreground">Required for Public visibility to appear on a community page.</p>
            </div>
            <div className="space-y-2">
              <Label>Expiration date &amp; time (optional)</Label>
              <div className="flex items-center gap-2">
                <Input
                  type="datetime-local"
                  value={formData.expires_at}
                  onChange={(e) => setFormData({ ...formData, expires_at: e.target.value })}
                />
                {formData.expires_at && (
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    onClick={() => setFormData({ ...formData, expires_at: "" })}
                  >
                    Clear
                  </Button>
                )}
              </div>
              <p className="text-xs text-muted-foreground">After this date and time the announcement will no longer be shown. Leave blank to keep it active indefinitely.</p>
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setModalOpen(false)}>Cancel</Button>
            <Button onClick={handleSave} disabled={saving}>{saving ? "Saving..." : editingId ? "Save Changes" : "Post Announcement"}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
