/**
 * @myropay/checkout — React & Next.js SDK
 *
 * npm install @myropay/checkout
 *
 * Usage:
 *   import { MyRoPayProvider, MyRoPayButton, useMyRoPay } from '@myropay/checkout';
 *
 *   // Wrap your app:
 *   <MyRoPayProvider><App /></MyRoPayProvider>
 *
 *   // In a component:
 *   const { openCheckout } = useMyRoPay();
 *   openCheckout({ publicKey: 'pk_live_...', amount: 5000, currency: 'NGN', ... });
 */
import React, { useState, useCallback, useEffect, useRef, createContext, useContext } from 'react';

const CHECKOUT_BASE = 'https://app.myropay.com';
const API_BASE      = `${CHECKOUT_BASE}/checkout/api`;

// ---- Types ----
export interface LineItem {
  name:   string;
  qty?:   number;
  price:  number;
  image?: string;
}

export interface SplitParty {
  email:     string;
  label:     string;
  type:      'percentage' | 'flat';
  value:     number;
}

export interface Milestone {
  title:     string;
  amount:    number;
  dueDate?:  string;
}

export interface InstalmentLeg {
  amount:   number;
  dueDate:  string;
}

export interface CheckoutOptions {
  publicKey:            string;
  amount?:              number;
  currency?:            string;
  orderRef?:            string;
  description?:         string;
  lineItems?:           LineItem[];
  customer?:            { email: string; name?: string; phone?: string };
  paymentMethods?:      ('card' | 'bank_transfer' | 'ussd' | 'mobile_money' | 'wallet' | 'escrow')[];
  // Session types
  sessionType?:         'standard' | 'instalment' | 'donation' | 'subscription';
  // Escrow
  escrow?:              boolean;
  escrowCondition?:     string;
  escrowDeadlineDays?:  number;
  milestones?:          Milestone[];
  splitParties?:        SplitParty[];
  // Instalments
  instalmentPlan?:      InstalmentLeg[];
  // Donations
  minAmount?:           number;
  suggestedAmounts?:    number[];
  // Subscriptions
  subscriptionInterval?: 'daily' | 'weekly' | 'monthly' | 'quarterly' | 'yearly';
  // Branding
  brandColor?:          string;
  brandLogo?:           string;
  // URLs
  successUrl?:          string;
  cancelUrl?:           string;
  // Misc
  metadata?:            Record<string, unknown>;
  customFields?:        { name: string; label: string; type?: string; required?: boolean }[];
  sessionId?:           string;   // pass if session was created server-side
  // Callbacks
  onSuccess?:           (data: { session_id: string; status: string }) => void;
  onEscrowFunded?:      (data: { session_id: string; escrow_id: string }) => void;
  onClose?:             () => void;
  onError?:             (message: string) => void;
}

export interface SessionResponse {
  session_id:   string;
  checkout_url: string;
  amount:       number;
  currency:     string;
  status:       string;
  expires_at:   string;
}

// ---- Context ----
interface MyRoPayContextValue {
  openCheckout:  (options: CheckoutOptions) => Promise<void>;
  closeCheckout: () => void;
  createSession: (options: CheckoutOptions) => Promise<SessionResponse>;
  isOpen:        boolean;
}

const MyRoPayContext = createContext<MyRoPayContextValue | null>(null);

export function useMyRoPay(): MyRoPayContextValue {
  const ctx = useContext(MyRoPayContext);
  if (!ctx) throw new Error('useMyRoPay must be used inside <MyRoPayProvider>');
  return ctx;
}

// ---- Provider ----
export function MyRoPayProvider({ children }: { children: React.ReactNode }) {
  const [isOpen, setIsOpen]       = useState(false);
  const [sessionId, setSessionId] = useState<string | null>(null);
  const [curOpts, setCurOpts]     = useState<CheckoutOptions | null>(null);
  const iframeRef                 = useRef<HTMLIFrameElement>(null);

  const createSession = useCallback(async (opts: CheckoutOptions): Promise<SessionResponse> => {
    const res = await fetch(`${API_BASE}/sessions.php`, {
      method:  'POST',
      headers: { 'Content-Type': 'application/json', 'X-Api-Key': opts.publicKey },
      body: JSON.stringify({
        amount:               opts.amount,
        currency:             opts.currency ?? 'NGN',
        order_ref:            opts.orderRef,
        description:          opts.description,
        line_items:           opts.lineItems,
        customer:             opts.customer,
        payment_methods:      opts.paymentMethods,
        session_type:         opts.sessionType ?? 'standard',
        escrow:               opts.escrow,
        escrow_condition:     opts.escrowCondition,
        escrow_deadline_days: opts.escrowDeadlineDays,
        milestones:           opts.milestones,
        split_parties:        opts.splitParties,
        instalment_plan:      opts.instalmentPlan,
        min_amount:           opts.minAmount,
        suggested_amounts:    opts.suggestedAmounts,
        success_url:          opts.successUrl,
        cancel_url:           opts.cancelUrl,
        brand_color:          opts.brandColor,
        brand_logo:           opts.brandLogo,
        metadata:             opts.metadata,
        custom_fields:        opts.customFields,
      }),
    }).then(r => r.json());
    if (!res.session_id) throw new Error(res.error ?? 'Session creation failed');
    return res as SessionResponse;
  }, []);

  const openCheckout = useCallback(async (opts: CheckoutOptions) => {
    let sid = opts.sessionId;
    if (!sid) {
      try {
        const sess = await createSession(opts);
        sid = sess.session_id;
      } catch (e: unknown) {
        opts.onError?.((e as Error).message);
        return;
      }
    }
    setSessionId(sid);
    setCurOpts(opts);
    setIsOpen(true);
    if (typeof document !== 'undefined') document.body.style.overflow = 'hidden';
  }, [createSession]);

  const closeCheckout = useCallback(() => {
    setIsOpen(false);
    setSessionId(null);
    setCurOpts(null);
    if (typeof document !== 'undefined') document.body.style.overflow = '';
  }, []);

  useEffect(() => {
    if (!isOpen || typeof window === 'undefined') return;
    const handler = (event: MessageEvent) => {
      if (event.origin !== CHECKOUT_BASE) return;
      const { type, data } = (event.data ?? {}) as { type: string; data: Record<string, unknown> };
      if (type === 'MYROPAY_SUCCESS')      { closeCheckout(); curOpts?.onSuccess?.(data as never); }
      if (type === 'MYROPAY_CANCEL' || type === 'MYROPAY_CLOSE')
                                           { closeCheckout(); curOpts?.onClose?.(); }
      if (type === 'MYROPAY_ERROR')        { curOpts?.onError?.((data?.message as string) ?? 'Error'); }
      if (type === 'MYROPAY_ESCROW_FUNDED') { curOpts?.onEscrowFunded?.(data as never); }
      if (type === 'MYROPAY_RESIZE' && iframeRef.current && data?.height) {
        iframeRef.current.style.minHeight =
          Math.min(Math.max(data.height as number, 500), 850) + 'px';
      }
    };
    window.addEventListener('message', handler);
    return () => window.removeEventListener('message', handler);
  }, [isOpen, curOpts, closeCheckout]);

  return (
    <MyRoPayContext.Provider value={{ openCheckout, closeCheckout, createSession, isOpen }}>
      {children}
      {isOpen && sessionId && (
        <div
          style={{
            position: 'fixed', inset: 0, zIndex: 999999,
            background: 'rgba(0,0,0,0.75)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            padding: '20px',
          }}
          onClick={e => { if (e.target === e.currentTarget) { closeCheckout(); curOpts?.onClose?.(); } }}
        >
          <div style={{
            width: '100%', maxWidth: '460px', maxHeight: '90vh',
            borderRadius: '20px', overflow: 'hidden',
            boxShadow: '0 32px 80px rgba(0,0,0,0.6)',
          }}>
            <iframe
              ref={iframeRef}
              src={`${CHECKOUT_BASE}/pay?session=${sessionId}`}
              style={{ width: '100%', border: 'none', minHeight: '680px',
                       background: '#0A0F1E', display: 'block' }}
              allow="payment"
              title="MyRoPay Secure Checkout"
            />
          </div>
        </div>
      )}
    </MyRoPayContext.Provider>
  );
}

/** Pre-styled "Pay with MyRoPay" button */
export function MyRoPayButton({
  children, style, className, ...opts
}: CheckoutOptions & {
  children?:  React.ReactNode;
  style?:     React.CSSProperties;
  className?: string;
}) {
  const { openCheckout } = useMyRoPay();
  return (
    <button
      className={className}
      onClick={() => openCheckout(opts)}
      style={{
        display: 'inline-flex', alignItems: 'center', gap: '8px',
        background: 'linear-gradient(135deg, #1A3A7A, #4F8EFF)',
        color: '#fff', border: 'none', borderRadius: '12px',
        padding: '13px 24px', fontSize: '15px', fontWeight: 700,
        cursor: 'pointer', boxShadow: '0 4px 16px rgba(79,142,255,0.3)',
        fontFamily: 'inherit',
        ...style,
      }}
    >
      <svg width="20" height="20" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
        <rect x="2" y="7" width="18" height="11" rx="3" stroke="white" strokeWidth="1.8"/>
        <path d="M2 11h18" stroke="white" strokeWidth="1.8"/>
        <circle cx="6" cy="15" r="1.8" fill="white" fillOpacity="0.7"/>
      </svg>
      {children ?? 'Pay with MyRoPay'}
    </button>
  );
}

/** Inline embed (pass sessionId from your server) */
export function MyRoPayInline({
  sessionId, style, className,
}: {
  sessionId:  string;
  style?:     React.CSSProperties;
  className?: string;
}) {
  return (
    <iframe
      className={className}
      src={`${CHECKOUT_BASE}/pay?session=${sessionId}&mode=inline`}
      style={{
        width: '100%', border: 'none', borderRadius: '20px',
        minHeight: '600px', background: '#0A0F1E',
        display: 'block',
        ...style,
      }}
      allow="payment"
      title="MyRoPay Checkout"
    />
  );
}
