"use client";

import { useCallback, useEffect, useState } from "react";
import { toast } from "sonner";
import {
  CheckIcon,
  EnvelopeIcon,
  InboxIcon,
  MagnifyingGlassIcon,
  PaperAirplaneIcon,
  UserPlusIcon,
  XMarkIcon,
} from "@heroicons/react/24/outline";
import { Button } from "@/components/Button";
import { InviteCreatorDialog } from "@/components/dashboard/InviteCreatorDialog";
import { SocialProviderIcon } from "@/components/dashboard/SocialProviderIcon";
import { ErrorState } from "@/components/ui/ErrorState";
import { ConfirmDialog } from "@/components/ui/ConfirmDialog";
import { SectionHeader } from "@/components/ui/PageHeader";
import { Skeleton } from "@/components/ui/Skeleton";
import { StatusBadge } from "@/components/ui/StatusBadge";
import { ApiError, creatorSearchApi, publicProfilePath } from "@/lib/api";
import { buildCampaignRelatedCreatorFilters } from "@/lib/campaign-detail-ui";
import { applicationApi, invitationApi } from "@/lib/api/campaign-participation";
import {
  brandApplicationActions,
  brandInvitationActions,
} from "@/lib/campaign-opportunity";
import {
  applicationStatusBadgeVariant,
  applicationStatusLabel,
  invitationStatusBadgeVariant,
  invitationStatusLabel,
} from "@/lib/campaign-participation";
import { formatFollowerCount, formatRelativeTime } from "@/lib/format";
import { socialProviderLabel } from "@/lib/social-providers";
import type { Campaign, CampaignListMeta } from "@/types/campaign";
import type {
  CampaignApplication,
  CampaignInvitation,
  CreatorSummary,
} from "@/types/campaign-participation";
import type { SearchCreator } from "@/types/profile";

function ListSkeleton() {
  return (
    <div className="space-y-4">
      <Skeleton className="h-24 w-full" />
      <Skeleton className="h-24 w-full" />
    </div>
  );
}

function CreatorAvatar({
  name,
  imageUrl,
}: {
  name: string;
  imageUrl: string | null;
}) {
  const initial = name.trim().charAt(0).toUpperCase() || "?";
  if (imageUrl) {
    return (
      // eslint-disable-next-line @next/next/no-img-element -- remote API profile URLs
      <img
        src={imageUrl}
        alt=""
        className="h-9 w-9 shrink-0 rounded-full object-cover"
      />
    );
  }
  return (
    <span
      aria-hidden
      className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-line text-[0.75rem] font-semibold text-primary"
    >
      {initial}
    </span>
  );
}

function CreatorSocialLine({ creator }: { creator: CreatorSummary }) {
  const followers = formatFollowerCount(creator.followers);
  if (creator.platforms.length === 0 && followers == null) return null;
  return (
    <p className="mt-1 flex flex-wrap items-center gap-1.5 text-[0.75rem] text-ink-40">
      {creator.platforms.map((platform) => (
        <span key={platform} className="inline-flex items-center gap-1" title={socialProviderLabel(platform)}>
          <SocialProviderIcon provider={platform} className="size-3.5" />
          <span className="sr-only">{socialProviderLabel(platform)}</span>
        </span>
      ))}
      {followers != null ? <span>{followers} followers</span> : null}
    </p>
  );
}

function Pager({
  meta,
  disabled,
  onPageChange,
}: {
  meta: CampaignListMeta | null;
  disabled: boolean;
  onPageChange: (page: number) => void;
}) {
  if (!meta || meta.last_page <= 1) return null;
  return (
    <div className="flex items-center justify-between gap-3">
      <p className="text-[0.75rem] text-ink-40">
        Page {meta.current_page} of {meta.last_page}
      </p>
      <div className="flex gap-2">
        <Button
          size="sm"
          variant="secondary"
          disabled={meta.current_page <= 1 || disabled}
          onClick={() => onPageChange(meta.current_page - 1)}
        >
          Previous
        </Button>
        <Button
          size="sm"
          variant="secondary"
          disabled={meta.current_page >= meta.last_page || disabled}
          onClick={() => onPageChange(meta.current_page + 1)}
        >
          Next
        </Button>
      </div>
    </div>
  );
}

export function BrandCampaignApplicationsTab({
  campaign,
  discoverHref = "/dashboard/discover",
  onApplicationAccepted,
}: {
  campaign: Campaign;
  discoverHref?: string;
  /** Called after an application is accepted — parent should refresh activity and open Payments. */
  onApplicationAccepted?: () => void;
}) {
  const campaignId = campaign.id;
  const campaignIsActive = campaign.status === "active";
  const [invitations, setInvitations] = useState<CampaignInvitation[]>([]);
  const [applications, setApplications] = useState<CampaignApplication[]>([]);
  const [matches, setMatches] = useState<SearchCreator[]>([]);
  const [inviteMeta, setInviteMeta] = useState<CampaignListMeta | null>(null);
  const [appMeta, setAppMeta] = useState<CampaignListMeta | null>(null);
  const [invitePage, setInvitePage] = useState(1);
  const [appPage, setAppPage] = useState(1);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [busyKey, setBusyKey] = useState<string | null>(null);
  const [inviteUsername, setInviteUsername] = useState<string | null>(null);
  const [confirm, setConfirm] = useState<
    | { type: "accept" | "reject"; applicationId: number }
    | { type: "cancel"; invitationId: number }
    | null
  >(null);

  const load = useCallback(
    async (silent = false) => {
      if (!silent) setIsLoading(true);
      setError(null);
      try {
        const [invites, apps, related] = await Promise.all([
          invitationApi.listForCampaign(campaignId, { page: invitePage, per_page: 20 }),
          applicationApi.listForCampaign(campaignId, { page: appPage, per_page: 20 }),
          creatorSearchApi
            .search(buildCampaignRelatedCreatorFilters(campaign, { per_page: 4 }))
            .catch(() => ({ creators: [] as SearchCreator[] })),
        ]);
        setInvitations(invites.invitations);
        setInviteMeta(invites.meta);
        setApplications(apps.applications);
        setAppMeta(apps.meta);
        setMatches(related.creators.slice(0, 4));
      } catch (err) {
        setError(
          err instanceof ApiError ? err.message : "Unable to load applications and invitations.",
        );
      } finally {
        setIsLoading(false);
      }
    },
    [campaign, campaignId, invitePage, appPage],
  );

  useEffect(() => {
    void load();
  }, [load]);

  async function runAction(
    key: string,
    action: () => Promise<void>,
    success: string,
    afterSuccess?: () => void,
  ) {
    setBusyKey(key);
    try {
      await action();
      toast.success(success);
      await load(true);
      afterSuccess?.();
    } catch (err) {
      toast.error(err instanceof ApiError ? err.message : "Something went wrong.");
    } finally {
      setBusyKey(null);
      setConfirm(null);
    }
  }

  if (isLoading) return <ListSkeleton />;

  if (error) {
    return (
      <ErrorState
        title="Couldn’t load applications"
        message={error}
        retryLabel="Retry"
        onRetry={() => void load()}
      />
    );
  }

  return (
    <div className="space-y-8">
      <section className="space-y-3" aria-labelledby="applications-heading">
        <SectionHeader
          id="applications-heading"
          title="Applications"
          icon={<InboxIcon className="size-4" />}
        />
        {applications.length === 0 ? (
          <p className="text-[0.8125rem] text-ink-60">No applications yet.</p>
        ) : (
          <ul className="divide-y divide-line rounded-pv border border-line bg-surface">
            {applications.map((application) => {
              const displayName =
                application.creator.display_name?.trim() || application.creator.username;
              const actions = brandApplicationActions(application.status, campaignIsActive);
              return (
                <li
                  key={application.id}
                  className="flex flex-col gap-3 px-3 py-3 sm:flex-row sm:items-start sm:justify-between"
                >
                  <div className="flex min-w-0 gap-3">
                    <CreatorAvatar
                      name={displayName}
                      imageUrl={application.creator.profile_image}
                    />
                    <div className="min-w-0">
                      <p className="truncate text-[0.875rem] font-medium text-primary">
                        {displayName}
                      </p>
                      <p className="text-[0.75rem] text-ink-40">
                        @{application.creator.username}
                        {" · Submitted "}
                        {formatRelativeTime(application.created_at)}
                      </p>
                      <CreatorSocialLine creator={application.creator} />
                      {application.message ? (
                        <p className="mt-1 whitespace-pre-wrap text-[0.8125rem] text-ink-60">
                          {application.message}
                        </p>
                      ) : null}
                    </div>
                  </div>
                  <div className="flex flex-wrap items-center gap-2 sm:justify-end">
                    <StatusBadge variant={applicationStatusBadgeVariant(application.status)}>
                      {applicationStatusLabel(application.status)}
                    </StatusBadge>
                    <Button
                      size="sm"
                      variant="secondary"
                      href={publicProfilePath(application.creator.username)}
                    >
                      View profile
                    </Button>
                    {actions.canAccept ? (
                      <Button
                        size="sm"
                        disabled={busyKey !== null}
                        onClick={() =>
                          setConfirm({ type: "accept", applicationId: application.id })
                        }
                      >
                        <CheckIcon className="size-4" aria-hidden="true" />
                        <span>Accept</span>
                      </Button>
                    ) : null}
                    {actions.canReject ? (
                      <Button
                        size="sm"
                        variant="secondary"
                        disabled={busyKey !== null}
                        onClick={() =>
                          setConfirm({ type: "reject", applicationId: application.id })
                        }
                      >
                        <XMarkIcon className="size-4" aria-hidden="true" />
                        <span>Reject</span>
                      </Button>
                    ) : null}
                  </div>
                </li>
              );
            })}
          </ul>
        )}
        <Pager meta={appMeta} disabled={busyKey !== null} onPageChange={setAppPage} />
      </section>

      <section className="space-y-3" aria-labelledby="matching-creators-heading">
        <SectionHeader
          id="matching-creators-heading"
          title="Creators who match"
          description="These creators fit this campaign’s network, category, and country."
          icon={<UserPlusIcon className="size-4" />}
          action={
            <Button size="sm" variant="secondary" href={discoverHref}>
              <MagnifyingGlassIcon className="size-4" aria-hidden="true" />
              <span>Discover creators</span>
            </Button>
          }
        />

        {matches.length === 0 ? (
          <p className="text-[0.8125rem] text-ink-60">
            No creators match this campaign yet.
          </p>
        ) : (
          <ul className="divide-y divide-line rounded-pv border border-line bg-surface">
            {matches.map((creator) => {
              const displayName = creator.display_name?.trim() || creator.username;
              const summary: CreatorSummary = {
                username: creator.username,
                display_name: creator.display_name,
                profile_image: creator.profile_image,
                platforms: creator.platforms,
                followers: creator.followers,
              };
              const alreadyInvited = invitations.some(
                (invitation) =>
                  invitation.creator.username === creator.username &&
                  (invitation.status === "pending" || invitation.status === "accepted"),
              );
              return (
                <li
                  key={creator.username}
                  className="flex flex-col gap-3 px-3 py-3 sm:flex-row sm:items-center sm:justify-between"
                >
                  <div className="flex min-w-0 gap-3">
                    <CreatorAvatar name={displayName} imageUrl={creator.profile_image} />
                    <div className="min-w-0">
                      <p className="truncate text-[0.875rem] font-medium text-primary">
                        {displayName}
                      </p>
                      <p className="text-[0.75rem] text-ink-40">@{creator.username}</p>
                      <CreatorSocialLine creator={summary} />
                    </div>
                  </div>
                  <div className="flex flex-wrap items-center gap-2 sm:justify-end">
                    <Button
                      size="sm"
                      variant="secondary"
                      href={publicProfilePath(creator.username)}
                    >
                      View profile
                    </Button>
                    {campaignIsActive && !alreadyInvited ? (
                      <Button
                        size="sm"
                        disabled={busyKey !== null}
                        onClick={() => setInviteUsername(creator.username)}
                      >
                        <PaperAirplaneIcon className="size-4" aria-hidden="true" />
                        <span>Invite</span>
                      </Button>
                    ) : null}
                    {alreadyInvited ? (
                      <StatusBadge variant="neutral">Invited</StatusBadge>
                    ) : null}
                  </div>
                </li>
              );
            })}
          </ul>
        )}

        {!campaignIsActive ? (
          <p className="text-[0.8125rem] text-ink-60">
            Only active campaigns can send invitations.
          </p>
        ) : null}
      </section>

      <section className="space-y-3" aria-labelledby="invitations-heading">
        <SectionHeader
          id="invitations-heading"
          title="Invitations"
          icon={<EnvelopeIcon className="size-4" />}
        />

        {invitations.length === 0 ? (
          <p className="text-[0.8125rem] text-ink-60">No invitations sent yet.</p>
        ) : (
          <ul className="divide-y divide-line rounded-pv border border-line bg-surface">
            {invitations.map((invitation) => {
              const displayName =
                invitation.creator.display_name?.trim() || invitation.creator.username;
              const actions = brandInvitationActions(invitation.status);
              return (
                <li
                  key={invitation.id}
                  className="flex flex-col gap-3 px-3 py-3 sm:flex-row sm:items-start sm:justify-between"
                >
                  <div className="flex min-w-0 gap-3">
                    <CreatorAvatar
                      name={displayName}
                      imageUrl={invitation.creator.profile_image}
                    />
                    <div className="min-w-0">
                      <p className="truncate text-[0.875rem] font-medium text-primary">
                        {displayName}
                      </p>
                      <p className="text-[0.75rem] text-ink-40">
                        @{invitation.creator.username}
                        {" · Sent "}
                        {formatRelativeTime(invitation.created_at)}
                      </p>
                      <CreatorSocialLine creator={invitation.creator} />
                      {invitation.message ? (
                        <p className="mt-1 whitespace-pre-wrap text-[0.8125rem] text-ink-60">
                          {invitation.message}
                        </p>
                      ) : null}
                    </div>
                  </div>
                  <div className="flex flex-wrap items-center gap-2 sm:justify-end">
                    <StatusBadge variant={invitationStatusBadgeVariant(invitation.status)}>
                      {invitationStatusLabel(invitation.status)}
                    </StatusBadge>
                    <Button
                      size="sm"
                      variant="secondary"
                      href={publicProfilePath(invitation.creator.username)}
                    >
                      View profile
                    </Button>
                    {actions.canCancel ? (
                      <Button
                        size="sm"
                        variant="secondary"
                        disabled={busyKey !== null}
                        onClick={() =>
                          setConfirm({ type: "cancel", invitationId: invitation.id })
                        }
                      >
                        <XMarkIcon className="size-4" aria-hidden="true" />
                        <span>Cancel invite</span>
                      </Button>
                    ) : null}
                  </div>
                </li>
              );
            })}
          </ul>
        )}
        <Pager meta={inviteMeta} disabled={busyKey !== null} onPageChange={setInvitePage} />
      </section>

      {confirm?.type === "accept" ? (
        <ConfirmDialog
          title="Accept this application?"
          description="The creator will join the campaign. Next you’ll authorize payment so they can submit deliverables."
          confirmLabel="Accept application"
          busy={busyKey !== null}
          busyLabel="Accepting…"
          onCancel={() => setConfirm(null)}
          onConfirm={() =>
            void runAction(
              `accept-app-${confirm.applicationId}`,
              async () => {
                await applicationApi.accept(confirm.applicationId);
              },
              "Application accepted. Authorize payment next.",
              onApplicationAccepted,
            )
          }
        />
      ) : null}

      {confirm?.type === "reject" ? (
        <ConfirmDialog
          title="Reject this application?"
          description="The creator will be notified that this application was not accepted."
          confirmLabel="Reject application"
          busy={busyKey !== null}
          busyLabel="Rejecting…"
          onCancel={() => setConfirm(null)}
          onConfirm={() =>
            void runAction(
              `reject-app-${confirm.applicationId}`,
              async () => {
                await applicationApi.reject(confirm.applicationId);
              },
              "Application rejected.",
            )
          }
        />
      ) : null}

      {confirm?.type === "cancel" ? (
        <ConfirmDialog
          title="Cancel this invitation?"
          description="The pending invitation will be withdrawn. You can invite this creator again later."
          confirmLabel="Cancel invitation"
          busy={busyKey !== null}
          busyLabel="Cancelling…"
          onCancel={() => setConfirm(null)}
          onConfirm={() =>
            void runAction(
              `cancel-invite-${confirm.invitationId}`,
              async () => {
                await invitationApi.cancel(campaignId, confirm.invitationId);
              },
              "Invitation cancelled.",
            )
          }
        />
      ) : null}

      <InviteCreatorDialog
        username={inviteUsername ?? ""}
        open={inviteUsername !== null}
        preferredCampaignId={campaignId}
        onClose={() => setInviteUsername(null)}
        onSent={() => void load(true)}
      />
    </div>
  );
}
