import {memo, useEffect, useMemo, useState} from 'react';
import {useForm} from 'react-hook-form';
import {zodResolver} from '@hookform/resolvers/zod';
import {BillingLimitSchemas} from '@plunk/shared';
import {
  Alert,
  Button,
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  Input,
  Progress,
} from '@plunk/ui';
import {AlertCircle, AlertTriangle, Check} from 'lucide-react';
import {AnimatePresence, motion} from 'framer-motion';
import type {z} from 'zod';
import {type BillingLimitsData, type CategoryLimit, useBillingLimits} from '../lib/hooks/useBillingLimits';
import {network} from '../lib/network';

// Price per email in the smallest currency unit (e.g., cents for USD/EUR)
const PRICE_PER_EMAIL = 0.1; // 0.001 USD/EUR = 0.1 cents

/**
 * Calculate the monetary cost for a given number of emails
 * @param emailCount - Number of emails
 * @param currency - Currency code (e.g., 'usd', 'eur')
 * @returns Formatted currency string
 */
const formatEmailCost = (emailCount: number, currency: string | null): string => {
  if (!currency) {
    return '';
  }

  // Calculate cost in smallest currency unit (cents)
  const costInCents = emailCount * PRICE_PER_EMAIL;

  try {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: currency.toUpperCase(),
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    }).format(costInCents / 100);
  } catch {
    // Fallback if currency is invalid
    return `${(costInCents / 100).toFixed(2)} ${currency.toUpperCase()}`;
  }
};

interface BillingLimitsProps {
  projectId: string;
  hasSubscription: boolean;
  billingEnabled: boolean;
}

type LimitsFormValues = z.infer<typeof BillingLimitSchemas.update>;

export function BillingLimits({projectId, hasSubscription, billingEnabled}: BillingLimitsProps) {
  const [isEditing, setIsEditing] = useState(false);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  // Fetch billing limits using SWR (fetch for both free and paid tiers when billing is enabled)
  const {limitsData, isLoading, mutate} = useBillingLimits(projectId, billingEnabled);

  const form = useForm<LimitsFormValues>({
    resolver: zodResolver(BillingLimitSchemas.update),
    defaultValues: {
      workflows: null,
      campaigns: null,
      transactional: null,
    },
  });

  // Update form when limits data changes
  useEffect(() => {
    if (limitsData) {
      form.reset({
        workflows: limitsData.workflows.limit,
        campaigns: limitsData.campaigns.limit,
        transactional: limitsData.transactional.limit,
      });
    }
  }, [limitsData, form]);

  const onSubmit = async (values: LimitsFormValues) => {
    try {
      setErrorMessage(null);
      setSuccessMessage(null);

      await network.fetch<BillingLimitsData, typeof BillingLimitSchemas.update>(
        'PUT',
        `/users/@me/projects/${projectId}/billing-limits`,
        values,
      );

      // Revalidate SWR cache
      await mutate();
      setIsEditing(false);
      setSuccessMessage('Billing limits updated successfully');

      // Clear success message after 3 seconds
      setTimeout(() => setSuccessMessage(null), 3000);
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Failed to update billing limits');
    }
  };

  const handleCancel = () => {
    if (limitsData) {
      form.reset({
        workflows: limitsData.workflows.limit,
        campaigns: limitsData.campaigns.limit,
        transactional: limitsData.transactional.limit,
      });
    }
    setIsEditing(false);
    setErrorMessage(null);
  };

  // Free tier projects can view their usage but can't edit limits
  const canEditLimits = hasSubscription;

  // If billing is not enabled, don't show the component
  if (!billingEnabled) {
    return null;
  }

  if (isLoading) {
    return (
      <Card>
        <CardHeader>
          <CardTitle>Billing Limits</CardTitle>
          <CardDescription>Set monthly limits for each email category</CardDescription>
        </CardHeader>
        <CardContent>
          <p className="text-sm text-neutral-500">Loading...</p>
        </CardContent>
      </Card>
    );
  }

  return (
    <Card>
      <CardHeader>
        <CardTitle>Billing Limits</CardTitle>
        <CardDescription>
          {hasSubscription
            ? 'Set monthly limits for each email category. Limits reset on the 1st of each month.'
            : 'Free tier projects have a total limit of 1,000 emails per month across all categories.'}
        </CardDescription>
      </CardHeader>
      <CardContent>
        <div className="space-y-6">
          {/* Free tier info banner */}
          {!hasSubscription && limitsData && (
            <Alert>
              <AlertCircle className="h-4 w-4" />
              <div className="ml-2">
                <p className="text-sm">
                  You&apos;re on the free tier with 1,000 emails per month. Upgrade to a paid subscription for unlimited
                  emails or custom limits.
                </p>
              </div>
            </Alert>
          )}

          {/* Success/Error Messages */}
          <AnimatePresence mode="wait">
            {successMessage && (
              <motion.div
                initial={{opacity: 0, y: -10}}
                animate={{opacity: 1, y: 0}}
                exit={{opacity: 0}}
                className="p-3 bg-green-50 border border-green-200 rounded-lg text-sm text-green-800"
              >
                {successMessage}
              </motion.div>
            )}
            {errorMessage && (
              <motion.div
                initial={{opacity: 0, y: -10}}
                animate={{opacity: 1, y: 0}}
                exit={{opacity: 0}}
                className="p-3 bg-red-50 border border-red-200 rounded-lg text-sm text-red-800"
              >
                {errorMessage}
              </motion.div>
            )}
          </AnimatePresence>

          {/* Usage Display (when not editing) */}
          {!isEditing && limitsData && (
            <div className="space-y-4">
              {/* For free tier, show total usage across all categories */}
              {!hasSubscription ? (
                <UsageDisplay
                  category="Total Emails (All Categories)"
                  usage={limitsData.workflows}
                  currency={limitsData.currency}
                />
              ) : (
                <>
                  <UsageDisplay category="Workflows" usage={limitsData.workflows} currency={limitsData.currency} />
                  <UsageDisplay category="Campaigns" usage={limitsData.campaigns} currency={limitsData.currency} />
                  <UsageDisplay
                    category="Transactional"
                    usage={limitsData.transactional}
                    currency={limitsData.currency}
                  />
                </>
              )}

              {canEditLimits && (
                <div className="flex justify-end pt-4">
                  <Button onClick={() => setIsEditing(true)}>Edit Limits</Button>
                </div>
              )}
            </div>
          )}

          {/* Edit Form */}
          {isEditing && (
            <Form {...form}>
              <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
                <FormField
                  control={form.control}
                  name="workflows"
                  render={({field}) => {
                    const estimatedCost =
                      limitsData?.currency && field.value
                        ? formatEmailCost(Number(field.value), limitsData.currency)
                        : null;
                    return (
                      <FormItem>
                        <FormLabel>Workflow Emails Limit</FormLabel>
                        <FormControl>
                          <Input
                            type="number"
                            placeholder="Unlimited"
                            {...field}
                            value={field.value ?? ''}
                            onChange={e => field.onChange(e.target.value === '' ? null : e.target.value)}
                          />
                        </FormControl>
                        <FormDescription>
                          Maximum workflow emails per month. Leave empty for unlimited.
                          {estimatedCost && <span className="text-neutral-500"> ≈ {estimatedCost}/month</span>}
                        </FormDescription>
                        <FormMessage />
                      </FormItem>
                    );
                  }}
                />

                <FormField
                  control={form.control}
                  name="campaigns"
                  render={({field}) => {
                    const estimatedCost =
                      limitsData?.currency && field.value
                        ? formatEmailCost(Number(field.value), limitsData.currency)
                        : null;
                    return (
                      <FormItem>
                        <FormLabel>Campaign Emails Limit</FormLabel>
                        <FormControl>
                          <Input
                            type="number"
                            placeholder="Unlimited"
                            {...field}
                            value={field.value ?? ''}
                            onChange={e => field.onChange(e.target.value === '' ? null : e.target.value)}
                          />
                        </FormControl>
                        <FormDescription>
                          Maximum campaign emails per month. Leave empty for unlimited.
                          {estimatedCost && <span className="text-neutral-500"> ≈ {estimatedCost}/month</span>}
                        </FormDescription>
                        <FormMessage />
                      </FormItem>
                    );
                  }}
                />

                <FormField
                  control={form.control}
                  name="transactional"
                  render={({field}) => {
                    const estimatedCost =
                      limitsData?.currency && field.value
                        ? formatEmailCost(Number(field.value), limitsData.currency)
                        : null;
                    return (
                      <FormItem>
                        <FormLabel>Transactional Emails Limit</FormLabel>
                        <FormControl>
                          <Input
                            type="number"
                            placeholder="Unlimited"
                            {...field}
                            value={field.value ?? ''}
                            onChange={e => field.onChange(e.target.value === '' ? null : e.target.value)}
                          />
                        </FormControl>
                        <FormDescription>
                          Maximum transactional emails per month. Leave empty for unlimited.
                          {estimatedCost && <span className="text-neutral-500"> ≈ {estimatedCost}/month</span>}
                        </FormDescription>
                        <FormMessage />
                      </FormItem>
                    );
                  }}
                />

                <div className="flex justify-end gap-2 pt-4">
                  <Button type="button" variant="outline" onClick={handleCancel}>
                    Cancel
                  </Button>
                  <Button type="submit" disabled={form.formState.isSubmitting}>
                    {form.formState.isSubmitting ? 'Saving...' : 'Save Changes'}
                  </Button>
                </div>
              </form>
            </Form>
          )}
        </div>
      </CardContent>
    </Card>
  );
}

interface UsageDisplayProps {
  category: string;
  usage: CategoryLimit;
  currency: string | null;
}

const UsageDisplay = memo(function UsageDisplay({category, usage, currency}: UsageDisplayProps) {
  const statusColor = useMemo(() => {
    if (usage.isBlocked) return 'text-red-600';
    if (usage.isWarning) return 'text-orange-600';
    return 'text-green-600';
  }, [usage.isBlocked, usage.isWarning]);

  const progressColor = useMemo(() => {
    if (usage.isBlocked) return 'bg-red-600';
    if (usage.isWarning) return 'bg-orange-500';
    return 'bg-green-600';
  }, [usage.isBlocked, usage.isWarning]);

  const statusIcon = useMemo(() => {
    if (usage.isBlocked) return <AlertCircle className="h-4 w-4" />;
    if (usage.isWarning) return <AlertTriangle className="h-4 w-4" />;
    return <Check className="h-4 w-4" />;
  }, [usage.isBlocked, usage.isWarning]);

  const limitText = usage.limit === null ? 'Unlimited' : usage.limit.toLocaleString();

  // Calculate monetary values
  const usageCost = currency ? formatEmailCost(usage.usage, currency) : null;
  const limitCost = currency && usage.limit !== null ? formatEmailCost(usage.limit, currency) : null;

  return (
    <div className="border border-neutral-200 rounded-lg p-4">
      <div className="flex items-center justify-between mb-3">
        <div>
          <h3 className="font-medium text-neutral-900">{category}</h3>
          <div className="flex items-baseline gap-2 mt-1">
            <p className="text-sm text-neutral-600">
              {usage.usage.toLocaleString()} / {limitText} emails
            </p>
            {currency && (
              <>
                <span className="text-neutral-300">•</span>
                <p className="text-sm text-neutral-500">
                  {usageCost}
                  {limitCost && ` / ${limitCost}`}
                </p>
              </>
            )}
          </div>
        </div>
        <div className={`flex items-center gap-2 ${statusColor}`}>
          {statusIcon}
          <span className="text-sm font-medium">
            {usage.limit === null ? 'Unlimited' : `${Math.round(usage.percentage)}%`}
          </span>
        </div>
      </div>

      {usage.limit !== null && (
        <>
          <Progress value={Math.min(usage.percentage, 100)} className="h-2" indicatorClassName={progressColor} />

          {usage.isBlocked && (
            <Alert className="mt-3 bg-red-50 border-red-200 text-red-900">
              <AlertCircle className="h-4 w-4" />
              <div className="ml-2">
                <p className={'text-sm'}>
                  <strong>Limit reached:</strong> No more {category.toLowerCase()} emails can be sent this month.
                </p>
              </div>
            </Alert>
          )}

          {usage.isWarning && !usage.isBlocked && (
            <Alert className="mt-3 bg-orange-50 border-orange-200 text-orange-900">
              <AlertTriangle className="h-4 w-4" />
              <div className="ml-2">
                <p className="text-sm">
                  <strong>Warning:</strong> You&apos;ve used {Math.round(usage.percentage)}% of your{' '}
                  {category.toLowerCase()} email limit.
                </p>
              </div>
            </Alert>
          )}
        </>
      )}
    </div>
  );
});
