"use client";

import type { AuctionAccount, AuctionListing, AuctionListingStatus } from "@domainops/shared-types";
import {
  App,
  Button,
  Card,
  Form,
  Input,
  InputNumber,
  Popconfirm,
  Select,
  Table,
  Tag,
  Tooltip,
  Typography,
} from "antd";
import { CheckOutlined, CloseOutlined, DollarOutlined, SyncOutlined } from "@ant-design/icons";
import type { ColumnsType } from "antd/es/table";
import { useCallback, useEffect, useState } from "react";
import {
  createAuctionListing,
  listAuctionAccounts,
  listAuctionListings,
  markAuctionLost,
  markAuctionWon,
} from "@/lib/api/auctions";
import type { CreateAuctionListingInput } from "@/lib/api/auctions";
import { ApiError } from "@/lib/api/client";
import { SORT_DIRECTIONS, textCompare } from "@/lib/utils/sort";
import { titleCase } from "@/lib/utils/text";
import { PAGE_SIZE_OPTIONS } from "@/lib/hooks/useServerPagination";
import { ComingSoonNotice } from "@/components/features/ComingSoonNotice";
import { PageGuide } from "@/components/features/PageGuide";
import { AUCTIONS_GUIDES } from "@/lib/guides/auctions";
import { AddAuctionAccountModal } from "./AddAuctionAccountModal";
import { BidModal } from "./BidModal";
import { CheckStatusModal } from "./CheckStatusModal";

const STATUS_COLORS: Record<AuctionListingStatus, string> = {
  watching: "blue",
  bid_placed: "gold",
  won: "green",
  lost: "default",
};

export default function AuctionsPage() {
  const { message } = App.useApp();
  const [form] = Form.useForm<CreateAuctionListingInput>();

  const [accounts, setAccounts] = useState<AuctionAccount[]>([]);
  const [supportedPlatforms, setSupportedPlatforms] = useState<string[]>([]);
  const [isAddAccountOpen, setIsAddAccountOpen] = useState(false);

  const [listings, setListings] = useState<AuctionListing[]>([]);
  const [statusFilter, setStatusFilter] = useState<AuctionListingStatus | undefined>();
  const [isLoadingListings, setIsLoadingListings] = useState(false);
  const [isAdding, setIsAdding] = useState(false);

  const [checkingListing, setCheckingListing] = useState<AuctionListing | null>(null);
  const [biddingListing, setBiddingListing] = useState<AuctionListing | null>(null);
  const [selectedIds, setSelectedIds] = useState<number[]>([]);
  const [isBulkWorking, setIsBulkWorking] = useState(false);

  const loadAccounts = useCallback(async () => {
    try {
      const response = await listAuctionAccounts();
      setAccounts(response.accounts);
      setSupportedPlatforms(response.supported_platforms);
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't load auction accounts.");
    }
  }, [message]);

  const loadListings = useCallback(async () => {
    setIsLoadingListings(true);
    try {
      setListings(await listAuctionListings(statusFilter));
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't load tracked listings.");
    } finally {
      setIsLoadingListings(false);
    }
  }, [message, statusFilter]);

  useEffect(() => {
    // Accounts live on the Laravel API - a client fetch on mount, not a
    // state-sync bug.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void loadAccounts();
  }, [loadAccounts]);

  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void loadListings();
  }, [loadListings]);

  async function handleAddListing(values: CreateAuctionListingInput) {
    setIsAdding(true);
    try {
      await createAuctionListing(values);
      message.success(`${values.fqdn} is now being watched.`);
      form.resetFields();
      void loadListings();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't add that listing.");
    } finally {
      setIsAdding(false);
    }
  }

  async function handleMarkWon(listing: AuctionListing) {
    try {
      await markAuctionWon(listing.id);
      message.success(`${listing.fqdn} marked won - added to acquisition intake.`);
      void loadListings();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't mark that listing won.");
    }
  }

  async function handleMarkLost(listing: AuctionListing) {
    try {
      await markAuctionLost(listing.id);
      message.success(`${listing.fqdn} marked lost.`);
      void loadListings();
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't mark that listing lost.");
    }
  }

  const selectedOpenListings = listings.filter(
    (l) => selectedIds.includes(l.id) && (l.status === "watching" || l.status === "bid_placed"),
  );

  async function runBulk(targets: AuctionListing[], action: (l: AuctionListing) => Promise<unknown>, successLabel: string) {
    setIsBulkWorking(true);
    try {
      const results = await Promise.allSettled(targets.map(action));
      const succeeded = results.filter((r) => r.status === "fulfilled").length;
      const failed = results.length - succeeded;
      if (succeeded > 0) message.success(`${successLabel} for ${succeeded} listing${succeeded === 1 ? "" : "s"}.`);
      if (failed > 0) message.error(`Failed for ${failed} listing${failed === 1 ? "" : "s"}.`);
      setSelectedIds([]);
      void loadListings();
    } finally {
      setIsBulkWorking(false);
    }
  }

  async function handleBulkMarkWon() {
    await runBulk(selectedOpenListings, (l) => markAuctionWon(l.id), "Marked won");
  }

  async function handleBulkMarkLost() {
    await runBulk(selectedOpenListings, (l) => markAuctionLost(l.id), "Marked lost");
  }

  const columns: ColumnsType<AuctionListing> = [
    { title: "Domain", dataIndex: "fqdn", sorter: (a, b) => textCompare(a.fqdn, b.fqdn), sortDirections: SORT_DIRECTIONS, render: (v: string) => <span className="font-mono">{v}</span> },
    {
      title: "Account",
      render: (_, row) => row.auction_account?.label ?? "—",
    },
    {
      title: "Status",
      dataIndex: "status",
      render: (v: AuctionListingStatus) => <Tag color={STATUS_COLORS[v]}>{titleCase(v.replace("_", " "))}</Tag>,
    },
    {
      title: "Current price",
      dataIndex: "current_price",
      render: (v: string | null) => (v != null ? `$${Number(v).toFixed(2)}` : "—"),
    },
    {
      title: "Max bid",
      dataIndex: "max_bid",
      render: (v: string | null) => (v != null ? `$${Number(v).toFixed(2)}` : "—"),
    },
    {
      title: "Last checked",
      dataIndex: "last_checked_at",
      render: (v: string | null) => (v ? new Date(v).toLocaleString() : "Never"),
    },
    {
      title: "Actions",
      render: (_, row) => {
        const isOpen = row.status === "watching" || row.status === "bid_placed";
        return (
          <div className="flex items-center gap-2 flex-wrap">
            <Tooltip title="Check Status">
              <Button
                size="small"
                icon={<SyncOutlined />}
                onClick={() => setCheckingListing(row)}
                disabled={!isOpen}
                className="dms_auctions_check_status_btn"
              />
            </Tooltip>
            <Tooltip title="Place Bid">
              <Button
                size="small"
                icon={<DollarOutlined />}
                onClick={() => setBiddingListing(row)}
                disabled={!isOpen || !row.auction_account?.can_bid}
                className="dms_auctions_place_bid_btn"
              />
            </Tooltip>
            <Popconfirm
              title="Mark this listing won?"
              description="This will drop it into acquisition intake for the Add Domain picker."
              onConfirm={() => void handleMarkWon(row)}
              disabled={!isOpen}
            >
              <Tooltip title="Mark Won">
                <Button
                  size="small"
                  type="primary"
                  icon={<CheckOutlined />}
                  disabled={!isOpen}
                  className="dms_auctions_mark_won_btn"
                />
              </Tooltip>
            </Popconfirm>
            <Popconfirm
              title="Mark this listing lost?"
              onConfirm={() => void handleMarkLost(row)}
              disabled={!isOpen}
            >
              <Tooltip title="Mark Lost">
                <Button
                  size="small"
                  danger
                  icon={<CloseOutlined />}
                  disabled={!isOpen}
                  className="dms_auctions_mark_lost_btn"
                />
              </Tooltip>
            </Popconfirm>
          </div>
        );
      },
    },
  ];

  return (
    <div className="flex flex-col gap-4 page page-auctions">
      <ComingSoonNotice feature="Auctions" />
      <div className="flex items-center gap-2">
        <Typography.Title level={4} style={{ margin: 0 }}>
          Auctions
        </Typography.Title>
        <PageGuide guides={AUCTIONS_GUIDES} label="Auctions guide" />
      </div>

      <Card title="Auction Accounts" className="dms_auctions_accounts_card">
        <div className="flex items-center gap-3 flex-wrap">
          {accounts.map((account) => (
            <Tag key={account.id} color={account.can_bid ? "green" : "default"}>
              {account.label} ({account.platform}
              {account.can_bid ? ", can bid" : ", watch-only"})
            </Tag>
          ))}
          <Button onClick={() => setIsAddAccountOpen(true)} className="dms_auctions_add_account_btn">
            Add Auction Account
          </Button>
        </div>
        {accounts.length === 0 && (
          <Typography.Paragraph type="secondary" style={{ marginTop: 12, marginBottom: 0 }}>
            No auction accounts yet. Add one to start tracking listings.
          </Typography.Paragraph>
        )}
      </Card>

      <Card title="Track A Listing" className="dms_auctions_track_card">
        <Form<CreateAuctionListingInput>
          form={form}
          layout="inline"
          onFinish={handleAddListing}
          className="flex flex-wrap gap-3 dms_auctions_track_form"
        >
          <Form.Item name="fqdn" rules={[{ required: true, message: "Domain name" }]} className="dms_auctions_fqdn_field">
            <Input placeholder="niceword.com" style={{ width: 200 }} />
          </Form.Item>
          <Form.Item
            name="auction_account_id"
            rules={[{ required: true, message: "Account" }]}
            className="dms_auctions_account_field"
          >
            <Select
              placeholder="Account"
              style={{ width: 200 }}
              options={accounts.map((a) => ({ value: a.id, label: `${a.label} (${a.platform})` }))}
            />
          </Form.Item>
          <Form.Item name="listing_url" className="dms_auctions_listing_url_field">
            <Input placeholder="Listing URL (optional)" style={{ width: 240 }} />
          </Form.Item>
          <Form.Item name="max_bid" className="dms_auctions_max_bid_field">
            <InputNumber<number> placeholder="Max bid" min={0} step={0.01} prefix="$" style={{ width: 140 }} />
          </Form.Item>
          <Form.Item>
            <Button type="primary" htmlType="submit" loading={isAdding} className="dms_auctions_watch_btn">
              Watch
            </Button>
          </Form.Item>
        </Form>
      </Card>

      <Card
        title="Tracked Listings"
        className="dms_auctions_listings_card"
        extra={
          <Select
            allowClear
            placeholder="All statuses"
            style={{ width: 160 }}
            value={statusFilter}
            onChange={setStatusFilter}
            options={[
              { value: "watching", label: "Watching" },
              { value: "bid_placed", label: "Bid Placed" },
              { value: "won", label: "Won" },
              { value: "lost", label: "Lost" },
            ]}
            className="dms_auctions_status_filter_select"
          />
        }
      >
        {selectedIds.length > 0 && (
          <div className="flex items-center gap-2 flex-wrap mb-3 dms_auctions_bulk_bar">
            <Typography.Text>{selectedIds.length} selected</Typography.Text>
            <Popconfirm
              title="Mark the selected listings won?"
              description="This will drop each into acquisition intake for the Add Domain picker."
              onConfirm={handleBulkMarkWon}
            >
              <Button
                size="small"
                type="primary"
                icon={<CheckOutlined />}
                loading={isBulkWorking}
                className="dms_auctions_bulk_mark_won_btn"
              >
                Mark Won
              </Button>
            </Popconfirm>
            <Popconfirm title="Mark the selected listings lost?" onConfirm={handleBulkMarkLost}>
              <Button size="small" danger icon={<CloseOutlined />} loading={isBulkWorking} className="dms_auctions_bulk_mark_lost_btn">
                Mark Lost
              </Button>
            </Popconfirm>
            <Button size="small" onClick={() => setSelectedIds([])} className="dms_auctions_bulk_clear_btn">
              Clear
            </Button>
          </div>
        )}
        <Table<AuctionListing>
          rowKey="id"
          columns={columns}
          dataSource={listings}
          loading={isLoadingListings}
          rowSelection={{
            selectedRowKeys: selectedIds,
            onChange: (keys) => setSelectedIds(keys as number[]),
            getCheckboxProps: (record) => ({
              disabled: !(record.status === "watching" || record.status === "bid_placed"),
            }),
          }}
          pagination={{ showSizeChanger: true, pageSizeOptions: PAGE_SIZE_OPTIONS, showTotal: (count) => `${count} listings` }}
          className="dms_auctions_listings_table"
        />
      </Card>

      <AddAuctionAccountModal
        open={isAddAccountOpen}
        supportedPlatforms={supportedPlatforms}
        onClose={() => setIsAddAccountOpen(false)}
        onCreated={() => {
          setIsAddAccountOpen(false);
          void loadAccounts();
        }}
      />

      <CheckStatusModal
        listing={checkingListing}
        onClose={() => setCheckingListing(null)}
        onUpdated={() => {
          setCheckingListing(null);
          void loadListings();
        }}
      />

      <BidModal
        listing={biddingListing}
        onClose={() => setBiddingListing(null)}
        onUpdated={() => {
          setBiddingListing(null);
          void loadListings();
        }}
      />
    </div>
  );
}
