import { CalendarDaysIcon, CreditCardIcon, StarIcon } from "@heroicons/react/20/solid";
import { type MetaFunction } from "@remix-run/react";
import { type PlanDefinition } from "@trigger.dev/platform";
import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson";
import { Feedback } from "~/components/Feedback";
import { MainCenteredContainer, PageBody, PageContainer } from "~/components/layout/AppLayout";
import { Button, LinkButton } from "~/components/primitives/Buttons";
import { Callout } from "~/components/primitives/Callout";
import { DateTime } from "~/components/primitives/DateTime";
import { InfoPanel } from "~/components/primitives/InfoPanel";
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
import { Paragraph } from "~/components/primitives/Paragraph";
import { prisma } from "~/db.server";
import { featuresForRequest } from "~/features.server";
import { resolveOrgIdFromSlug } from "~/models/organization.server";
import { getCurrentPlan, getPlans } from "~/services/platform.v3.server";
import { dashboardLoader } from "~/services/routeBuilders/dashboardBuilder";
import {
  OrganizationParamsSchema,
  organizationPath,
  v3StripePortalPath,
} from "~/utils/pathBuilder";
import { PricingPlans } from "../resources.orgs.$organizationSlug.select-plan";

export const meta: MetaFunction = () => {
  return [
    {
      title: `Billing | Trigger.dev`,
    },
  ];
};

export const loader = dashboardLoader(
  {
    params: OrganizationParamsSchema,
    context: async (params) => {
      const organizationId = await resolveOrgIdFromSlug(params.organizationSlug);
      return organizationId ? { organizationId } : {};
    },
    authorization: {
      action: "manage",
      resource: { type: "billing" },
      message: "With your current role, you can't manage billing.",
    },
  },
  async ({ params, request, user }) => {
    const userId = user.id;
    const { organizationSlug } = params;

    const { isManagedCloud } = featuresForRequest(request);
    if (!isManagedCloud) {
      return redirect(organizationPath({ slug: organizationSlug }));
    }

    const organization = await prisma.organization.findFirst({
      where: { slug: organizationSlug, members: { some: { userId } } },
    });

    if (!organization) {
      throw new Response(null, { status: 404, statusText: "Organization not found" });
    }

    const currentPlan = await getCurrentPlan(organization.id);
    const showSelfServe = currentPlan?.v3Subscription?.showSelfServe !== false;

    //periods
    const periodStart = new Date();
    periodStart.setUTCHours(0, 0, 0, 0);
    periodStart.setUTCDate(1);

    const periodEnd = new Date();
    periodEnd.setUTCMonth(periodEnd.getMonth() + 1);
    periodEnd.setUTCDate(0);
    periodEnd.setUTCHours(0, 0, 0, 0);

    const daysRemaining = Math.ceil(
      (periodEnd.getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24)
    );

    // Extract 'message' from search params
    const url = new URL(request.url);
    const message = url.searchParams.get("message");

    if (!showSelfServe) {
      return typedjson({
        showSelfServe: false as const,
        ...currentPlan,
        organizationSlug,
        periodStart,
        periodEnd,
        daysRemaining,
        message,
      });
    }

    const plans = await getPlans();
    if (!plans) {
      throw new Response(null, { status: 404, statusText: "Plans not found" });
    }

    return typedjson({
      showSelfServe: true as const,
      ...plans,
      ...currentPlan,
      organizationSlug,
      periodStart,
      periodEnd,
      daysRemaining,
      message,
    });
  }
);

export default function ChoosePlanPage() {
  const loaderData = useTypedLoaderData<typeof loader>();

  const {
    showSelfServe,
    v3Subscription,
    organizationSlug,
    periodStart,
    periodEnd,
    daysRemaining,
    message,
  } = loaderData;

  return (
    <PageContainer>
      <NavBar>
        <PageTitle title="Billing" />
        <PageAccessories>
          {v3Subscription?.isPaying && showSelfServe && (
            <>
              <LinkButton
                to={v3StripePortalPath({ slug: organizationSlug })}
                variant="tertiary/small"
              >
                Invoices
              </LinkButton>
              <LinkButton
                to={v3StripePortalPath({ slug: organizationSlug })}
                variant="tertiary/small"
              >
                Manage card details
              </LinkButton>
            </>
          )}
        </PageAccessories>
      </NavBar>
      <PageBody scrollable={showSelfServe}>
        {showSelfServe ? (
          <div className="flex flex-col gap-3">
            {message && (
              <Callout variant="idea" className="mb-2">
                {message}
              </Callout>
            )}
            <div className="flex flex-col gap-y-3 divide-grid-bright rounded-sm border border-grid-bright bg-background-bright py-2 pr-1 text-text-bright lg:w-fit lg:flex-row lg:items-center lg:divide-x">
              <div className="flex gap-2 px-3 lg:items-center">
                <StarIcon className="size-5 min-w-5 lg:-mt-0.5" />
                {planLabel(
                  v3Subscription?.plan,
                  v3Subscription?.canceledAt !== undefined,
                  periodEnd
                )}
              </div>
              {v3Subscription?.isPaying ? (
                <div className="flex gap-2 px-3 lg:items-center">
                  <CalendarDaysIcon className="size-5 min-w-5 lg:-mt-0.5" />
                  Billing period: <DateTime
                    date={periodStart}
                    includeTime={false}
                    timeZone="UTC"
                  />{" "}
                  to <DateTime date={periodEnd} includeTime={false} timeZone="UTC" /> (
                  {daysRemaining} days remaining)
                </div>
              ) : null}
            </div>
            <div>
              <PricingPlans
                plans={loaderData.plans}
                concurrencyAddOnPricing={loaderData.addOnPricing.concurrency}
                subscription={v3Subscription}
                organizationSlug={organizationSlug}
                hasPromotedPlan={false}
                periodEnd={periodEnd}
              />
            </div>
          </div>
        ) : (
          <MainCenteredContainer className="max-w-md">
            <InfoPanel
              title="Billing"
              icon={CreditCardIcon}
              iconClassName="text-emerald-500"
              panelClassName="max-w-full"
              accessory={
                <Feedback
                  defaultValue="enterprise"
                  button={<Button variant="secondary/small">Contact us</Button>}
                />
              }
            >
              <Paragraph spacing variant="small">
                Your billing is managed by our team.
              </Paragraph>
              <Paragraph spacing variant="small">
                Get in touch for invoices, plan changes, or other billing questions.
              </Paragraph>
            </InfoPanel>
          </MainCenteredContainer>
        )}
      </PageBody>
    </PageContainer>
  );
}

function planLabel(plan: PlanDefinition | undefined, canceled: boolean, periodEnd: Date) {
  if (!plan || plan.type === "free") {
    return "You're on the Free plan";
  }

  if (plan.type === "enterprise") {
    return "You're on the Enterprise plan";
  }

  const text = `You're on the $${plan.tierPrice}/mo ${plan.title} plan`;

  if (canceled) {
    return (
      <>
        {text}. From <DateTime includeTime={false} date={periodEnd} /> you're on the Free plan.
      </>
    );
  }

  return text;
}
