import {
  BeakerIcon,
  BellAlertIcon,
  BookOpenIcon,
  ChatBubbleLeftRightIcon,
  ClockIcon,
  PlusIcon,
  QuestionMarkCircleIcon,
  RectangleGroupIcon,
  RectangleStackIcon,
  Squares2X2Icon,
} from "@heroicons/react/20/solid";
import { useLocation } from "react-use";
import { AIChatIcon } from "~/assets/icons/AIChatIcon";
import { BranchEnvironmentIconSmall } from "~/assets/icons/EnvironmentIcons";
import { WaitpointTokenIcon } from "~/assets/icons/WaitpointTokenIcon";
import openBulkActionsPanel from "~/assets/images/open-bulk-actions-panel.png";
import selectRunsIndividually from "~/assets/images/select-runs-individually.png";
import selectRunsUsingFilters from "~/assets/images/select-runs-using-filters.png";
import { useEnvironment } from "~/hooks/useEnvironment";
import { useFeatures } from "~/hooks/useFeatures";
import { useOrganization } from "~/hooks/useOrganizations";
import { useProject } from "~/hooks/useProject";
import { type MinimumEnvironment } from "~/presenters/SelectBestEnvironmentPresenter.server";
import { type BranchableEnvironmentToken } from "~/utils/branchableEnvironment";
import { NewBranchPanel } from "~/routes/resources.branches.create";
import { GitHubSettingsPanel } from "~/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.github";
import {
  docsPath,
  v3BillingPath,
  v3CreateBulkActionPath,
  v3EnvironmentPath,
  v3NewProjectAlertPath,
  v3NewSchedulePath,
} from "~/utils/pathBuilder";
import { AskAI } from "./AskAI";
import { CodeBlock } from "./code/CodeBlock";
import { InlineCode } from "./code/InlineCode";
import { environmentFullTitle, EnvironmentIcon } from "./environments/EnvironmentLabel";
import { Feedback } from "./Feedback";
import { EnvironmentSelector } from "./navigation/EnvironmentSelector";
import { Button, LinkButton } from "./primitives/Buttons";
import {
  ClientTabs,
  ClientTabsContent,
  ClientTabsList,
  ClientTabsTrigger,
} from "./primitives/ClientTabs";
import { Header1 } from "./primitives/Headers";
import { InfoPanel } from "./primitives/InfoPanel";
import { Paragraph } from "./primitives/Paragraph";
import { StepNumber } from "./primitives/StepNumber";
import { TextLink } from "./primitives/TextLink";
import { SimpleTooltip } from "./primitives/Tooltip";
import {
  InitCommandV3,
  PackageManagerProvider,
  TriggerDeployStep,
  TriggerDevStepV3,
} from "./SetupCommands";
import { StepContentContainer } from "./StepContentContainer";
import { V4Badge } from "./V4Badge";

export function HasNoTasksDev() {
  return (
    <PackageManagerProvider>
      <div>
        <div className="mb-6 flex items-center justify-between border-b">
          <Header1 spacing>Get setup in 3 minutes</Header1>
          <div className="flex items-center gap-2">
            <Feedback
              button={
                <Button variant="minimal/small" LeadingIcon={ChatBubbleLeftRightIcon}>
                  I'm stuck!
                </Button>
              }
              defaultValue="help"
            />
          </div>
        </div>
        <StepNumber stepNumber="1" title="Run the CLI 'init' command in an existing project" />
        <StepContentContainer>
          <InitCommandV3 />
          <Paragraph spacing>
            You'll notice a new folder in your project called{" "}
            <InlineCode variant="small">trigger</InlineCode>. We've added a few simple example tasks
            in there to help you get started.
          </Paragraph>
        </StepContentContainer>
        <StepNumber stepNumber="2" title="Run the CLI 'dev' command" />
        <StepContentContainer>
          <TriggerDevStepV3 />
        </StepContentContainer>
        <StepNumber stepNumber="3" title="Waiting for tasks" displaySpinner />
        <StepContentContainer>
          <Paragraph>This page will automatically refresh.</Paragraph>
        </StepContentContainer>
      </div>
    </PackageManagerProvider>
  );
}

export function HasNoTasksDeployed({ environment }: { environment: MinimumEnvironment }) {
  return <DeploymentOnboardingSteps />;
}

export function SchedulesNoPossibleTaskPanel() {
  return (
    <InfoPanel
      title="Create your first scheduled task"
      icon={ClockIcon}
      iconClassName="text-schedules"
      panelClassName="max-w-full"
      accessory={
        <LinkButton
          to={docsPath("v3/tasks-scheduled")}
          variant="docs/small"
          LeadingIcon={BookOpenIcon}
        >
          How to schedule tasks
        </LinkButton>
      }
    >
      <Paragraph spacing variant="small">
        You have no scheduled tasks in your project. Before you can schedule a task you need to
        create a <InlineCode>schedules.task</InlineCode>.
      </Paragraph>
    </InfoPanel>
  );
}

export function SchedulesNoneAttached() {
  const organization = useOrganization();
  const project = useProject();
  const environment = useEnvironment();
  const location = useLocation();

  return (
    <InfoPanel
      title="Attach your first schedule"
      icon={ClockIcon}
      iconClassName="text-schedules"
      panelClassName="max-w-full"
    >
      <Paragraph spacing variant="small">
        Scheduled tasks will only run automatically if you connect a schedule to them, you can do
        this in the dashboard or using the SDK.
      </Paragraph>
      <div className="flex gap-2">
        <LinkButton
          to={`${v3NewSchedulePath(organization, project, environment)}${location.search}`}
          variant="secondary/medium"
          LeadingIcon={RectangleGroupIcon}
          className="inline-flex"
          leadingIconClassName="text-blue-500"
        >
          Use the dashboard
        </LinkButton>
        <LinkButton
          to={docsPath("v3/tasks-scheduled")}
          variant="docs/medium"
          LeadingIcon={BookOpenIcon}
          className="inline-flex"
        >
          Use the SDK
        </LinkButton>
      </div>
    </InfoPanel>
  );
}

export function BatchesNone() {
  return (
    <InfoPanel
      title="Triggering batches"
      icon={Squares2X2Icon}
      iconClassName="text-batches"
      panelClassName="max-w-full"
      accessory={
        <LinkButton to={docsPath("triggering")} variant="docs/small" LeadingIcon={BookOpenIcon}>
          How to trigger batches
        </LinkButton>
      }
    >
      <Paragraph spacing variant="small">
        You have no batches in this environment. You can trigger batches from your backend or from
        inside other tasks.
      </Paragraph>
    </InfoPanel>
  );
}

export function SessionsNone() {
  return (
    <InfoPanel
      title="Sessions"
      icon={AIChatIcon}
      iconClassName="text-sessions"
      panelClassName="max-w-full"
      accessory={
        <LinkButton
          to={docsPath("ai-chat/sessions")}
          variant="docs/small"
          LeadingIcon={BookOpenIcon}
        >
          Sessions docs
        </LinkButton>
      }
    >
      <Paragraph spacing variant="small">
        A session is a stateful execution of an agent, with two-way streaming and durable compute. A
        single session can have multiple runs associated with it, so one conversation can span many
        task triggers. The input stream carries incoming user messages, and the output stream
        carries everything the agent produces, including AI generation parts (text, reasoning, tool
        calls, etc.) and any custom data parts your task emits.
      </Paragraph>
      <Paragraph spacing variant="small">
        The easiest way to create one is to trigger a <InlineCode>chat.agent</InlineCode> task,
        which is built on sessions and handles the chat turn loop for you. You can also call{" "}
        <InlineCode>sessions.start()</InlineCode> directly for non-chat patterns like agent inboxes,
        approval flows, or server-to-server streaming.
      </Paragraph>
    </InfoPanel>
  );
}

export function TestHasNoTasks() {
  const organization = useOrganization();
  const project = useProject();
  const environment = useEnvironment();
  return (
    <InfoPanel
      title="You don't have any tasks to test"
      icon={BeakerIcon}
      iconClassName="text-tests"
      panelClassName="max-w-full"
      accessory={
        <LinkButton
          to={v3EnvironmentPath(organization, project, environment)}
          variant="primary/small"
        >
          Create a task
        </LinkButton>
      }
    >
      <Paragraph spacing variant="small">
        Before testing a task, you must first create one. Follow the instructions on the{" "}
        <TextLink to={v3EnvironmentPath(organization, project, environment)}>Tasks page</TextLink>{" "}
        to create a task, then return here to test it.
      </Paragraph>
    </InfoPanel>
  );
}

export function DeploymentsNone() {
  return <DeploymentOnboardingSteps />;
}

export function DeploymentsNoneDev() {
  const organization = useOrganization();
  const project = useProject();
  const environment = useEnvironment();

  return (
    <>
      <div className="mb-6 flex items-center justify-between border-b">
        <div className="mb-2 flex items-center gap-2">
          <EnvironmentIcon environment={environment} className="-ml-1 size-8" />
          <Header1>Deploy your tasks</Header1>
        </div>
        <div className="flex items-center">
          <SimpleTooltip
            button={
              <LinkButton
                variant="small-menu-item"
                LeadingIcon={BookOpenIcon}
                leadingIconClassName="text-blue-500"
                to={docsPath("deployment/overview")}
              />
            }
            content="Deploy docs"
          />
          <SimpleTooltip
            button={
              <LinkButton
                variant="small-menu-item"
                LeadingIcon={QuestionMarkCircleIcon}
                leadingIconClassName="text-blue-500"
                to={docsPath("troubleshooting#deployment")}
              />
            }
            content="Troubleshooting docs"
          />
          <AskAI />
        </div>
      </div>
      <StepNumber stepNumber="→" title="Switch to a deployed environment" />
      <StepContentContainer className="mb-4 flex flex-col gap-4">
        <Paragraph>
          This is the Development environment. When you're ready to deploy your tasks, switch to a
          different environment.
        </Paragraph>
        <EnvironmentSelector
          organization={organization}
          project={project}
          environment={environment}
          className="w-fit border border-border-bright bg-secondary hover:border-border-brighter hover:bg-surface-control"
        />
      </StepContentContainer>
    </>
  );
}

export function AlertsNoneDev() {
  return (
    <div className="space-y-8">
      <InfoPanel
        icon={BellAlertIcon}
        iconClassName="text-alerts"
        title="Adding alerts"
        panelClassName="max-w-full"
      >
        <Paragraph spacing variant="small">
          You can get alerted when deployed runs fail.
        </Paragraph>
        <Paragraph spacing variant="small">
          We don't support alerts in the Development environment. Switch to a deployed environment
          to setup alerts.
        </Paragraph>
        <div className="flex gap-3">
          <LinkButton
            to={docsPath("troubleshooting-alerts")}
            variant="docs/medium"
            LeadingIcon={BookOpenIcon}
            className="inline-flex"
          >
            How to setup alerts
          </LinkButton>
        </div>
      </InfoPanel>
      <SwitcherPanel />
    </div>
  );
}

export function AlertsNoneDeployed() {
  const organization = useOrganization();
  const project = useProject();
  const environment = useEnvironment();

  return (
    <div className="space-y-8">
      <InfoPanel
        icon={BellAlertIcon}
        iconClassName="text-alerts"
        title="Adding alerts"
        panelClassName="max-w-full"
      >
        <Paragraph spacing variant="small">
          You can get alerted when deployed runs fail. We currently support sending Slack, Email,
          and webhooks.
        </Paragraph>

        <div className="flex items-center justify-between gap-3">
          <LinkButton
            to={docsPath("troubleshooting-alerts")}
            variant="docs/medium"
            LeadingIcon={BookOpenIcon}
            className="inline-flex"
          >
            Alerts docs
          </LinkButton>
          <LinkButton
            to={v3NewProjectAlertPath(organization, project, environment)}
            variant="primary/medium"
            LeadingIcon={PlusIcon}
            shortcut={{ key: "n" }}
          >
            New alert
          </LinkButton>
        </div>
      </InfoPanel>
    </div>
  );
}

export function QueuesHasNoTasks() {
  const organization = useOrganization();
  const project = useProject();
  const environment = useEnvironment();

  return (
    <InfoPanel
      title="You don't have any queues"
      icon={RectangleStackIcon}
      iconClassName="text-queues"
      panelClassName="max-w-md"
      accessory={
        <LinkButton
          to={v3EnvironmentPath(organization, project, environment)}
          variant="primary/small"
        >
          Create a task
        </LinkButton>
      }
    >
      <Paragraph spacing variant="small">
        Queues will appear here when you have created a task in this environment. Follow the
        instructions on the{" "}
        <TextLink to={v3EnvironmentPath(organization, project, environment)}>Tasks page</TextLink>{" "}
        to create a task, then return here to see its queue.
      </Paragraph>
    </InfoPanel>
  );
}

export function NoWaitpointTokens() {
  return (
    <InfoPanel
      title="You don't have any waitpoint tokens"
      icon={WaitpointTokenIcon}
      iconClassName="text-sky-500"
      panelClassName="max-w-md"
      accessory={
        <LinkButton to={docsPath("wait-for-token")} variant="docs/small" LeadingIcon={BookOpenIcon}>
          Waitpoint docs
        </LinkButton>
      }
    >
      <Paragraph spacing variant="small">
        Waitpoint tokens pause task runs until you complete the token. They're commonly used for
        approval workflows and other scenarios where you need to wait for external confirmation,
        such as human-in-the-loop processes.
      </Paragraph>
    </InfoPanel>
  );
}

export function BranchesNoBranchableEnvironment({ showSelfServe }: { showSelfServe: boolean }) {
  const { isManagedCloud } = useFeatures();
  const organization = useOrganization();

  if (!isManagedCloud) {
    return (
      <InfoPanel
        title="Create a preview environment"
        icon={BranchEnvironmentIconSmall}
        iconClassName="text-preview"
        panelClassName="max-w-full"
      >
        <Paragraph spacing variant="small">
          To add branches you need to have a <InlineCode>RuntimeEnvironment</InlineCode> where{" "}
          <InlineCode>isBranchableEnvironment</InlineCode> is true. We recommend creating a
          dedicated one using the "PREVIEW" type.
        </Paragraph>
      </InfoPanel>
    );
  }

  return (
    <InfoPanel
      title="Upgrade to get preview branches"
      icon={BranchEnvironmentIconSmall}
      iconClassName="text-preview"
      panelClassName="max-w-full"
      accessory={
        showSelfServe ? (
          <LinkButton variant="primary/small" to={v3BillingPath(organization)}>
            Upgrade
          </LinkButton>
        ) : (
          <Feedback
            button={<Button variant="secondary/small">Request more</Button>}
            defaultValue="enterprise"
          />
        )
      }
    >
      <Paragraph spacing variant="small">
        Preview branches in Trigger.dev create isolated environments for testing new features before
        production.
      </Paragraph>
      <Paragraph variant="small">
        You must be on <V4Badge inline /> to access preview branches. Read our{" "}
        <TextLink to={docsPath("upgrade-to-v4")}>upgrade to v4 guide</TextLink> to learn more.
      </Paragraph>
    </InfoPanel>
  );
}

export function BranchesNoBranches({
  env,
  limits,
  canUpgrade,
  showSelfServe,
}: {
  env: BranchableEnvironmentToken;
  limits: { used: number; limit: number };
  canUpgrade: boolean;
  showSelfServe: boolean;
}) {
  const organization = useOrganization();

  const envTextClassName = env === "preview" ? "text-preview" : "text-dev";
  const branchesLabel = env === "preview" ? "preview branches" : "dev branches";

  if (limits.used >= limits.limit) {
    return (
      <InfoPanel
        title={`Upgrade to get ${branchesLabel}`}
        icon={BranchEnvironmentIconSmall}
        iconClassName={envTextClassName}
        panelClassName="max-w-full"
        accessory={
          showSelfServe && canUpgrade ? (
            <LinkButton variant="primary/small" to={v3BillingPath(organization)}>
              Upgrade
            </LinkButton>
          ) : (
            <Feedback
              button={
                <Button variant={showSelfServe ? "primary/small" : "secondary/small"}>
                  Request more
                </Button>
              }
              defaultValue={showSelfServe ? "help" : "enterprise"}
            />
          )
        }
      >
        <Paragraph spacing variant="small">
          You've reached the limit ({limits.used}/{limits.limit}) of branches for your plan. Upgrade
          to get branches.
        </Paragraph>
      </InfoPanel>
    );
  }

  return (
    <InfoPanel
      title="Create your first branch"
      icon={BranchEnvironmentIconSmall}
      iconClassName={envTextClassName}
      panelClassName="max-w-full"
      accessory={
        <NewBranchPanel
          button={
            <Button
              variant="primary/small"
              LeadingIcon={PlusIcon}
              leadingIconClassName="text-white"
            >
              New branch
            </Button>
          }
          env={env}
        />
      }
    >
      <Paragraph spacing variant="small">
        Branches are a way to test new features in isolation before merging them into the main
        environment.
      </Paragraph>
      <Paragraph spacing variant="small">
        Branches are only available when using <V4Badge inline /> or above. Read our{" "}
        <TextLink to={docsPath("upgrade-to-v4")}>v4 upgrade guide</TextLink> to learn more.
      </Paragraph>
    </InfoPanel>
  );
}

export function SwitcherPanel({ title = "Switch to a deployed environment" }: { title?: string }) {
  const organization = useOrganization();
  const project = useProject();
  const environment = useEnvironment();

  return (
    <div className="flex items-center rounded-md border border-grid-bright bg-background-bright p-3">
      <Paragraph variant="small" className="grow">
        {title}
      </Paragraph>
      <EnvironmentSelector
        organization={organization}
        project={project}
        environment={environment}
        className="w-auto grow-0 rounded-sm bg-grid-bright"
      />
    </div>
  );
}

export function BulkActionsNone() {
  const organization = useOrganization();
  const project = useProject();
  const environment = useEnvironment();

  return (
    <div>
      <div className="mb-6 flex items-center justify-between border-b pb-0.5">
        <Header1 spacing>Create a bulk action</Header1>
        <div className="flex items-center gap-2">
          <LinkButton
            variant="primary/small"
            LeadingIcon={PlusIcon}
            to={v3CreateBulkActionPath(organization, project, environment)}
          >
            New bulk action
          </LinkButton>
        </div>
      </div>
      <StepNumber stepNumber="1" title="Select runs individually" />
      <StepContentContainer className="mb-4 flex flex-col gap-4">
        <Paragraph>Select runs from the runs page individually.</Paragraph>
        <div>
          <img src={selectRunsIndividually} alt="Select runs individually" />
        </div>
      </StepContentContainer>
      <div className="mb-5 ml-9 flex items-center gap-2">
        <div className="h-px w-full bg-grid-bright" />
        <Paragraph variant="extra-small" className="text-text-dimmed">
          OR
        </Paragraph>
        <div className="h-px w-full bg-grid-bright" />
      </div>
      <StepNumber stepNumber="2" title="Select runs using filters" />
      <StepContentContainer className="flex flex-col gap-4">
        <Paragraph>
          Use the filter menu on the runs page to select just the runs you want to bulk action.
        </Paragraph>
        <div>
          <img src={selectRunsUsingFilters} alt="Select runs using filters" />
        </div>
      </StepContentContainer>
      <StepNumber stepNumber="3" title="Open the bulk action panel" />
      <StepContentContainer className="flex flex-col gap-4">
        <Paragraph>Click the “Bulk actions” button in the top right of the runs page.</Paragraph>
        <div>
          <img src={openBulkActionsPanel} alt="Open the bulk action panel" />
        </div>
      </StepContentContainer>
    </div>
  );
}

function DeploymentOnboardingSteps() {
  const environment = useEnvironment();
  const organization = useOrganization();
  const project = useProject();

  return (
    <PackageManagerProvider>
      <div className="mb-2 flex items-center justify-between border-b">
        <div className="mb-2 flex min-w-0 items-center gap-2">
          <EnvironmentIcon environment={environment} className="-ml-1 size-8 shrink-0" />
          <Header1 className="truncate">
            Deploy your tasks to {environmentFullTitle(environment)}
          </Header1>
        </div>
        <div className="flex items-center">
          <SimpleTooltip
            button={
              <LinkButton
                variant="small-menu-item"
                LeadingIcon={BookOpenIcon}
                leadingIconClassName="text-blue-500"
                to={docsPath("deployment/overview")}
              />
            }
            content="Deploy docs"
          />
          <SimpleTooltip
            button={
              <LinkButton
                variant="small-menu-item"
                LeadingIcon={QuestionMarkCircleIcon}
                leadingIconClassName="text-blue-500"
                to={docsPath("troubleshooting#deployment")}
              />
            }
            content="Troubleshooting docs"
          />
          <AskAI />
        </div>
      </div>
      <ClientTabs defaultValue="github">
        <ClientTabsList variant="segmented" className="mb-6">
          <ClientTabsTrigger value={"github"} variant="segmented" layoutId="deploy-tabs">
            GitHub
          </ClientTabsTrigger>
          <ClientTabsTrigger value={"cli"} variant="segmented" layoutId="deploy-tabs">
            Manual
          </ClientTabsTrigger>
          <ClientTabsTrigger value={"github-actions"} variant="segmented" layoutId="deploy-tabs">
            GitHub Actions
          </ClientTabsTrigger>
        </ClientTabsList>
        <ClientTabsContent value={"github"}>
          <StepNumber stepNumber="1" title="Connect your GitHub repository" />
          <StepContentContainer>
            <Paragraph spacing>
              Deploy automatically with every push. Read the{" "}
              <TextLink to={docsPath("github-integration")}>full guide</TextLink>.
            </Paragraph>
            <div className="w-fit">
              <GitHubSettingsPanel
                organizationSlug={organization.slug}
                projectSlug={project.slug}
                environmentSlug={environment.slug}
                billingPath={v3BillingPath({ slug: organization.slug })}
              />
            </div>
          </StepContentContainer>
        </ClientTabsContent>
        <ClientTabsContent value={"cli"}>
          <StepNumber stepNumber="1" title="Run the CLI 'deploy' command" />
          <StepContentContainer>
            <Paragraph spacing>
              This will deploy your tasks to the {environmentFullTitle(environment)} environment.
              Read the <TextLink to={docsPath("deployment/overview")}>full guide</TextLink>.
            </Paragraph>
            <TriggerDeployStep environment={environment} />
          </StepContentContainer>
        </ClientTabsContent>
        <ClientTabsContent value={"github-actions"}>
          <StepNumber stepNumber="1" title="Deploy using GitHub Actions" />
          <StepContentContainer>
            <Paragraph spacing>
              Read the <TextLink to={docsPath("github-actions")}>GitHub Actions guide</TextLink> to
              get started.
            </Paragraph>
          </StepContentContainer>
        </ClientTabsContent>
      </ClientTabs>

      <StepNumber stepNumber="2" title="Waiting for tasks to deploy" displaySpinner />
      <StepContentContainer>
        <Paragraph>This page will automatically refresh when your tasks are deployed.</Paragraph>
      </StepContentContainer>
    </PackageManagerProvider>
  );
}

export function PromptsNone() {
  return (
    <InfoPanel
      title="Define your first prompt"
      icon={AIChatIcon}
      iconClassName="text-aiPrompts"
      panelClassName="max-w-lg"
      accessory={
        <LinkButton
          to={docsPath("prompt-management")}
          variant="docs/small"
          LeadingIcon={BookOpenIcon}
        >
          Prompts docs
        </LinkButton>
      }
    >
      <Paragraph spacing variant="small">
        Managed prompts let you define AI prompts in code with typesafe variables, then edit and
        version them from the dashboard without redeploying.
      </Paragraph>
      <Paragraph spacing variant="small">
        Add a prompt to your project using <InlineCode variant="small">prompts.define()</InlineCode>
        :
      </Paragraph>
      <CodeBlock
        code={`import { prompts } from "@trigger.dev/sdk";
import { z } from "zod";

export const myPrompt = prompts.define({
  id: "my-prompt",
  variables: z.object({
    name: z.string(),
  }),
  content: \`Hello {{name}}!\`,
});`}
        showLineNumbers={false}
        showOpenInModal={false}
      />
      <Paragraph variant="small" className="mt-2">
        Deploy your project and your prompts will appear here with version history and a live
        editor.
      </Paragraph>
    </InfoPanel>
  );
}
