//
// Copyright (c) 2025-2026 rustmailer.com (https://rustmailer.com)
//
// This file is part of the Bichon Email Archiving Project
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


import { dateFnsLocaleMap, formatBytes } from "@/lib/utils"
import { format, formatDistanceToNow } from "date-fns"
import { MessageSquareText, Paperclip } from "lucide-react"
import { Skeleton } from "@/components/ui/skeleton"
import { Checkbox } from "@/components/ui/checkbox"
import { EmailEnvelope } from "@/api"
import { useSearchContext } from "./context"
import { MailBulkActions } from "./bulk-actions"
import { useTranslation } from 'react-i18next'
import { enUS } from "date-fns/locale"
import { ColumnDef } from "@tanstack/react-table"
import LongText from "@/components/long-text"
import { DataTableColumnHeader } from "./table/data-table-column-header"
import { SearchTable } from "./table/table"
import { DataTableRowActions } from "./table/data-table-row-actions"
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { DataTableToolbar } from "./table/toolbar"
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card"
import { useSearchMessages } from "@/hooks/use-search-messages"

interface MailListProps {
  items: EmailEnvelope[]
  isLoading: boolean
  onEnvelopeChanged: (envelope: EmailEnvelope) => void
  setSortBy: (sortBy: "DATE" | "SIZE") => void
  setSortOrder: (value: "desc" | "asc") => void
}

export function MailListTable({
  items,
  isLoading,
  onEnvelopeChanged,
  setSortBy,
  setSortOrder
}: MailListProps) {
  const { t, i18n } = useTranslation()

  const locale = dateFnsLocaleMap[i18n.language.toLowerCase()] ?? enUS
  const { selected, setSelected } = useSearchContext()

  const columns: ColumnDef<EmailEnvelope>[] = [
    {
      accessorKey: "id",
      header: () => (
        <Checkbox
          checked={
            totalSelected === items.length && items.length > 0
              ? true
              : totalSelected > 0
                ? "indeterminate"
                : false
          }
          onCheckedChange={handleToggleAll}
          className="h-4 w-4"
        />
      ),
      cell: ({ row }) => (
        <Checkbox
          checked={hasSelected(row.original.account_id, row.original.id)}
          onCheckedChange={() => toggleSelected(row.original.account_id, row.original.id)}
          onClick={(e) => e.stopPropagation()}
          className="h-4 w-4 shrink-0"
        />
      ),
      meta: { className: 'text-left text-sm' },
      minSize: 25,
      maxSize: 25,
    },
    {
      accessorKey: "account_email",
      header: t('search.account'),
      cell: ({ row }) => {
        const { setFilter } = useSearchMessages();
        const { account_email, account_id } = row.original;

        return (
          <div
            className="group relative flex items-center w-full h-full px-2 cursor-pointer"
            onClick={(e) => {
              e.stopPropagation();
              setFilter((prev: any) => ({
                ...prev,
                account_ids: [account_id],
                mailbox_ids: undefined
              }))
            }}
          >
            <div className="absolute left-0 top-1 bottom-1 w-0.5 bg-primary opacity-0 group-hover:opacity-100 transition-opacity duration-150" />
            <div className="absolute inset-x-2 bottom-0.5 h-[1px] bg-primary scale-x-0 group-hover:scale-x-100 transition-transform duration-200 origin-left" />
            <span className="truncate flex-1 min-w-0 group-hover:text-primary transition-colors">
              <LongText className='text-xs'>{account_email}</LongText>
            </span>
          </div>
        );
      },
      meta: { className: 'w-[150px]' },
      minSize: 150, maxSize: 150,
    },
    {
      accessorKey: "mailbox_name",
      header: t('search.mailbox'),
      cell: ({ row }) => {
        const { setFilter } = useSearchMessages();
        const { mailbox_name, mailbox_id, account_id, tags } = row.original;

        if (!mailbox_name) return null;
        const safeTags = tags ?? [];
        const visibleTags = safeTags.slice(0, 2);

        return (
          <div
            className="group relative flex items-center w-full min-w-0 h-full px-2 cursor-pointer"
            onClick={(e) => {
              e.stopPropagation();
              setFilter((prev: any) => ({
                ...prev,
                account_ids: [account_id],
                mailbox_ids: [mailbox_id]
              }))
            }}
          >
            <div className="absolute left-0 top-1 bottom-1 w-0.5 bg-primary opacity-0 group-hover:opacity-100 transition-opacity duration-150" />
            <div className="absolute inset-x-2 bottom-0.5 h-[1px] bg-primary scale-x-0 group-hover:scale-x-100 transition-transform duration-200 origin-left" />

            <div className="flex flex-col min-w-0 flex-1">
              <span className="text-[11px] truncate font-medium leading-none group-hover:text-primary transition-colors">
                {mailbox_name}
              </span>
              <div className="flex flex-wrap gap-1 mt-1">
                {visibleTags.map((tag, i) => (
                  <span key={i} className="px-1.5 py-0.5 rounded-sm bg-primary/10 text-primary text-[9px] font-medium leading-none border border-primary/20 whitespace-nowrap">
                    {tag}
                  </span>
                ))}
                {safeTags.length > 2 && (
                  <span className="px-1.5 py-0.5 rounded-sm bg-gray-100 text-gray-500 text-[9px] font-medium leading-none border border-gray-200">
                    +{safeTags.length - 2}
                  </span>
                )}
              </div>
            </div>
          </div>
        );
      },
      meta: { className: 'text-xs' },
      maxSize: 120,
    },
    {
      accessorKey: "from",
      header: t('search.from'),
      cell: ({ row }) => {
        const fromEmail = row.original.from;
        const { setFilter } = useSearchMessages();

        return (
          <div
            className="group relative flex items-center w-full min-w-0 h-full px-2 cursor-pointer"
            onClick={(e) => {
              e.stopPropagation();
              setFilter((prev: Record<string, any>) => ({ ...prev, from: fromEmail }))
            }}
          >
            <div className="absolute left-0 top-1 bottom-1 w-0.5 bg-primary opacity-0 group-hover:opacity-100 transition-opacity duration-150" />
            <div className="absolute inset-x-2 bottom-0.5 h-[1px] bg-primary scale-x-0 group-hover:scale-x-100 transition-transform duration-200 origin-left" />
            <LongText className="text-xs flex-1 truncate group-hover:text-primary transition-colors">
              {fromEmail}
            </LongText>
          </div>
        );
      },
      meta: { className: 'text-left text-xs' },
      minSize: 150,
      maxSize: 300,
    },
    {
      accessorKey: "to",
      header: t('search.to'),
      cell: ({ row }) => {
        const recipients = row.original.to || [];
        const { setFilter } = useSearchMessages();

        return (
          <div className="group relative flex items-center w-full min-w-0 h-full px-2 overflow-hidden">
            <div className="absolute left-0 top-0 bottom-0 w-[2px] bg-primary opacity-0 group-hover:opacity-100 transition-opacity" />

            <div className="text-xs flex flex-wrap gap-x-1 min-w-0 flex-1">
              {recipients.map((email, index) => (
                <span key={index} className="flex items-center">
                  <button
                    type="button"
                    onClick={(e) => {
                      e.stopPropagation();
                      setFilter((prev: Record<string, any>) => ({ ...prev, to: email }));
                    }}
                    className="hover:text-primary hover:underline transition-colors truncate max-w-[150px]"
                  >
                    {email}
                  </button>
                  {index < recipients.length - 1 && (
                    <span className="text-muted-foreground ml-0.5">,</span>
                  )}
                </span>
              ))}
            </div>
          </div>
        );
      },
      meta: { className: 'text-left text-xs' },
      minSize: 150,
      maxSize: 200,
    },
    {
      accessorKey: "subject",
      header: t('search.subject'),
      cell: ({ row }) => <LongText className='text-xs'>{row.original.subject}</LongText>,
      meta: { className: 'text-left text-xs' },
      maxSize: 450,
    },
    {
      id: "text_preview",
      header: () => null,
      cell: ({ row }) => {
        const preview = row.original.preview

        if (!preview) return null

        return (
          <HoverCard openDelay={200} closeDelay={150}>
            <HoverCardTrigger asChild>
              <button
                type="button"
                className="text-muted-foreground hover:text-primary transition"
                onClick={(e) => e.stopPropagation()}
              >
                <MessageSquareText size={16} />
              </button>
            </HoverCardTrigger>

            <HoverCardContent
              side="right"
              align="start"
              className="max-w-[520px] max-h-[420px] overflow-auto whitespace-pre-wrap text-xs leading-relaxed"
            >
              {preview}
            </HoverCardContent>
          </HoverCard>
        )
      },
      meta: { className: "text-center max-w-[80px]" },
      minSize: 36,
      maxSize: 36,
      enableSorting: false,
    },
    {
      id: "attachment_count",
      header: () => <Paperclip size={16} />,
      cell: ({ row }) => <span className='text-xs'>{row.original.regular_attachment_count}</span>,
      meta: { className: 'text-left text-xs' },
      minSize: 40,
      maxSize: 40
    },
    {
      accessorKey: 'size',
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title={t('search.size')} />
      ),
      cell: ({ row }) => <span className='text-xs max-w-[40px]'>{formatBytes(row.original.size)}</span>,
      meta: { className: 'text-left text-xs' },
      minSize: 100,
      maxSize: 100,
    },
    {
      accessorKey: 'date',
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title={t('search.date')} />
      ),
      cell: ({ row }) => {
        const date = new Date(row.original.date)
        const title = format(date, 'yyyy-MM-dd HH:mm:ss')
        return (
          <Tooltip>
            <TooltipTrigger asChild>
              <span className='text-xs whitespace-nowrap'>
                {formatDistanceToNow(date, { addSuffix: true, locale })}
              </span>
            </TooltipTrigger>
            <TooltipContent>{title}</TooltipContent>
          </Tooltip>
        )
      },
      meta: { className: 'text-left text-xs' },
      minSize: 130,
      maxSize: 130,
    },
    {
      id: 'actions',
      header: t('users.columns.actions'),
      cell: DataTableRowActions,
      meta: { className: 'text-right text-xs' },
      minSize: 50,
      maxSize: 60,
    },
  ]

  const handleToggleAll = () => {
    const total = Array.from(selected.values()).reduce((sum, set) => sum + set.size, 0)

    if (total === items.length && items.length > 0) {
      setSelected(new Map())
    } else {
      setSelected(prev => {
        const next = new Map(prev)
        for (const item of items) {
          const set = new Set(next.get(item.account_id) || [])
          set.add(item.id)
          next.set(item.account_id, set)
        }
        return next
      })
    }
  }

  const toggleSelected = (accountId: number, mailId: string) => {
    setSelected(prev => {
      const next = new Map(prev)
      const set = new Set(next.get(accountId) || [])

      if (set.has(mailId)) {
        set.delete(mailId)
        if (set.size === 0) next.delete(accountId)
        else next.set(accountId, set)
      } else {
        set.add(mailId)
        next.set(accountId, set)
      }
      return next
    })
  }

  const totalSelected = Array.from(selected.values()).reduce((sum, set) => sum + set.size, 0)

  const hasSelected = (accountId: number, mailId: string) => selected.get(accountId)?.has(mailId) ?? false

  if (isLoading) {
    return (
      <div className="divide-y divide-border">
        {Array.from({ length: 8 }).map((_, i) => (
          <div key={i} className="flex items-center gap-2 px-2 py-1.5">
            <Skeleton className="h-3 w-3" />
            <Skeleton className="h-3 w-3 rounded-full" />
            <Skeleton className="h-3 flex-1" />
            <Skeleton className="h-2.5 w-16" />
          </div>
        ))}
      </div>
    )
  }

  return (
    <>
      <SearchTable
        data={items}
        columns={columns}
        onRowClick={(e, row) => {
          const target = e.target as HTMLElement
          if (target.closest('input[type="checkbox"], button')) return
          onEnvelopeChanged(row.original)
        }}
        setSortBy={setSortBy}
        setSortOrder={setSortOrder}
      >
        {(table) => {
          return <DataTableToolbar table={table} />
        }}

      </SearchTable>
      {totalSelected > 0 && <MailBulkActions />}
    </>
  )
}
