// import { ExtensionManifest } from './models/extension';
import { ExtensionContext, ExtensionManifest, ScriptDefinition } from './models/extension';
import MyzrokDashboard from './pages/MyzrokDashboard';
import CustomDomainsPage from './pages/CustomDomainsPage';
import CustomDomainDetail from './pages/CustomDomainDetail';
import PaymentIcon from '@mui/icons-material/Payment';
import LanguageIcon from '@mui/icons-material/Language';
import "./assets/styles/chargebee.css";
import "./assets/styles/myzrok.css";
import './api/runtime';
import './api/apis/index';
import './api/models/index';

import * as joi from 'joi';
import { Buffer } from 'buffer';
import { User } from './models/user';
import { BillingAccountApi, PlanApi, SubscriptionApi } from './api/apis/index';
import { BillingAccount, Plan, Subscription } from './api/models/index';
import { BillingProvider } from './models/billingProvider';
import { U } from 'react-svg-credit-card-payment-icons/UnionPay-BKtojwLB';
import { BillingDetails, BillingInformation, CardDetails } from './models/billing';
import { AccordionState } from './components/BillingSummary';
import { createSessionConfig } from './api/apiConfig';
import { sessionLogout } from './api/sessionApi';

const CHARGEBEE_BILLING_PROVIDER_ID = 'FDC4C74E-EE08-4C15-8BFB-714FF21FAA6F';

export type MyzrokExtensionState = {
  billingAccount?: BillingAccount
  billingProvider?: BillingProvider
  plans: Plan[]
  billingInformation?: BillingInformation
  billingDetails?: BillingDetails
  cardDetails?: CardDetails
  accordionState?: AccordionState,
  subscription?: Subscription
}

// Scripts to inject in <head> - loaded early
const headScripts: ScriptDefinition[] = [
  // Example: Inline script for early initialization
  {
    src: 'https://js.chargebee.com/v2/chargebee.js'
    
  }
];

const bodyScripts: ScriptDefinition[] = [
  // Example: Inline script for early initialization
  {
    content: `  Chargebee.init({
        site: 'nfdev-test',
        publishableKey: 'test_Wfkcdw4ph4Gcun67LvqCAxMs5nOaqxQWfj'
      });`,
    defer: true
    
  }
];

const defaultBillingProvider: BillingProvider = {
  id: CHARGEBEE_BILLING_PROVIDER_ID,
  name: "Chargebee"
}

// Initial state
const initialState: MyzrokExtensionState = {
  billingAccount: undefined,
  billingProvider: undefined,
  plans: [],
  billingInformation: undefined,
  billingDetails: undefined,
  cardDetails: undefined,
  accordionState: undefined,
  subscription: undefined
};

const manifest: ExtensionManifest = {
  id: 'my-extension',
  name: 'My Extension',
  version: '1.0.0',
  headScripts: headScripts,
  bodyScripts: bodyScripts,
  initialState: initialState,
  onUserLogin: onUserLogin,
  onUserLogout: onUserLogout,
  routes: [
    {
      path: '/billing',
      component: MyzrokDashboard,
    },
    {
      path: '/domains',
      component: CustomDomainsPage,
    },
    {
      path: '/domains/:customDomainId',
      component: CustomDomainDetail,
    },
  ],
  navItems: [
    {
      id: 'billing-nav',
      label: 'Billing',
      icon: PaymentIcon,
      path: '/billing',
    },
    {
      id: 'domains-nav',
      label: 'Custom Domains',
      icon: LanguageIcon,
      path: '/domains',
    },
  ],
};

  export function getPlans(billingProviderId: string, context: ExtensionContext) {

    const plansApi = new PlanApi(createSessionConfig());

    // wrap the request in a promise so that the calling code can wait for the response
    return new Promise(async (resolve, reject) => {
      await plansApi.listPlans({billingProviderId: billingProviderId, deleted: false}).then((plans: Plan[]) => {
        context.setState<MyzrokExtensionState>({plans: plans})
        resolve(plans);
      }).catch((error) => {
        // TODO - actual error handling
        context.setState<MyzrokExtensionState>({plans: []})
        resolve([]);
        
      })
    });
  }

  export async function getBillingAccount(billingProviderId: string, zrokEmail: string, context: ExtensionContext) {
    const billingAccountApi = new BillingAccountApi(createSessionConfig());

    return new Promise((resolve, reject) => {
      // if the billing account has not already been set

      // look up the billing account based on the provider ID and their zrok email
      billingAccountApi.listBillingAccounts({billingProviderId: billingProviderId, email: zrokEmail}).then(async (billingAccounts: BillingAccount[] | undefined) => {
        if(billingAccounts && billingAccounts.length == 1) {

          // if there is one result, retrieve the account to get the payment information as well
          await getBillingAccountAndCardDetails(billingAccounts[0]).then(async (detailedBillingAccount: BillingAccount) => {
            // set the billing context
            //await setBillingContext(detailedBillingAccount);
            context.setState<MyzrokExtensionState>({billingAccount: detailedBillingAccount})
            resolve(detailedBillingAccount);
            
          }).catch((error) => {
            console.error(error);
            context.setState<MyzrokExtensionState>({billingAccount: undefined})
            reject(error);
          });

          // if there are more than one billing accounts returned
        } else if(billingAccounts && billingAccounts.length > 1) {
          // this should not happen, raise an error
          console.error("More than one billing account was found for user with email " + zrokEmail + " in billing provider " + billingProviderId + ". This should not happen!")
          context.setState<MyzrokExtensionState>({billingAccount: undefined})
          reject(new Error("Could not retrieve billing account, multiple active billing accounts exist for this user. Please contact support for help"));
        } else {
          // no account exists yet for the user, do the minimal amount of stubbing for the context so the account can be created
          // setBillingContext(undefined);
          context.setState<MyzrokExtensionState>({billingAccount: undefined})
          resolve(undefined)
        }
      }).catch((error) => {
        reject(error);
      });
    });
  }

    /**
     * function for obtaining the billing account with the card details. Find does not return the card details (as it would require calling chargebee to get the card details on each result)
     * @param billingAccount the billing account to obtain the card details for
     * @returns promise of the result of looking up the detailed billing account
     */
    async function getBillingAccountAndCardDetails(billingAccount: BillingAccount): Promise<BillingAccount> {
      const billingAccountApi = new BillingAccountApi(createSessionConfig());

      return new Promise((resolve, reject) => {
        billingAccountApi.getBillingAccount({id: billingAccount.id}).then((detailedBillingAccount: BillingAccount) => {
          if(detailedBillingAccount) {
            resolve(detailedBillingAccount)
          } else {
            reject(new Error("Failed to find billing account!"));
          }
        }).catch((error) => {
          console.error(error);
          reject(error);
        });
      });
    }

function onUserLogin(user: User, context: ExtensionContext): void  {
  context.setState<MyzrokExtensionState>({billingProvider: defaultBillingProvider});
}

function onUserLogout(context: ExtensionContext): void {
  sessionLogout().catch((error) => console.error("Failed to end the billing session cleanly", error));
  context.setState<MyzrokExtensionState>({plans: []});
  context.setState<MyzrokExtensionState>({billingAccount: undefined});
  context.setState<MyzrokExtensionState>({billingProvider: undefined})
}
export default manifest;