import { Injectable, inject } from '@angular/core';
import { FormSelect } from '../../../../shared/components/form/form-select/form-select';
import { Observable, catchError, map, of, throwError } from 'rxjs';
import {
  CountryLookupDto,
  CountryService,
} from '../../../global-masters/countries/public-api';
import {
  CurrencyLookupDto,
  CurrencyService,
} from '../../../global-masters/currencies/public-api';
import {
  LanguageLookupDto,
  LanguageService,
} from '../../../global-masters/languages/public-api';
import {
  TimezoneLookupDto,
  TimezoneService,
} from '../../../global-masters/timezones/public-api';
import { OrganizationOnboardingDraft } from '../models/organization-draft.model';
import {
  CountryLocalizationDefaults,
  DateFormatValue,
  FiscalYearConventionValue,
  NumberFormatValue,
  OnboardingLookupValue,
  OrganizationLicenseType,
  OrganizationPlanDefaults,
  OrganizationPlanLookupValue,
  TimeFormatValue,
} from '../models/organization-onboarding.model';
import {
  OrganizationProvisioningRequest,
  OrganizationProvisioningResult,
} from '../models/organization-provisioning.model';

const ORGANIZATION_ONBOARDING_DRAFT_KEY = 'organization-onboarding-draft-v1';

const ORGANIZATION_TYPE_OPTIONS: readonly OnboardingLookupValue[] = [
  { id: 'enterprise', label: 'Enterprise' },
  { id: 'group', label: 'Group' },
  { id: 'non-profit', label: 'Non Profit' },
  { id: 'public-sector', label: 'Public Sector' },
];

const INDUSTRY_OPTIONS: readonly OnboardingLookupValue[] = [
  { id: 'healthcare', label: 'Healthcare' },
  { id: 'manufacturing', label: 'Manufacturing' },
  { id: 'professional-services', label: 'Professional Services' },
  { id: 'retail', label: 'Retail' },
  { id: 'technology', label: 'Technology' },
];

const SUBSCRIPTION_PLAN_OPTIONS: readonly OrganizationPlanLookupValue[] = [
  { id: 'starter', label: 'Starter', code: 'STARTER' },
  { id: 'growth', label: 'Growth', code: 'GROWTH' },
  { id: 'enterprise', label: 'Enterprise', code: 'ENTERPRISE' },
];

const PLAN_DEFAULTS: readonly OrganizationPlanDefaults[] = [
  {
    plan: { id: 'starter', label: 'Starter', code: 'STARTER' },
    licenseType: 'Trial',
    maximumCompanies: 1,
    maximumUsers: 10,
    maximumStorageGb: 10,
    limitsEditable: true,
  },
  {
    plan: { id: 'growth', label: 'Growth', code: 'GROWTH' },
    licenseType: 'Paid',
    maximumCompanies: 5,
    maximumUsers: 100,
    maximumStorageGb: 100,
    limitsEditable: true,
  },
  {
    plan: { id: 'enterprise', label: 'Enterprise', code: 'ENTERPRISE' },
    licenseType: 'Paid',
    maximumCompanies: 25,
    maximumUsers: 1000,
    maximumStorageGb: 500,
    limitsEditable: true,
  },
];

const DATE_FORMAT_OPTIONS: readonly FormSelect<DateFormatValue>[] = [
  // { value: 'DD/MM/YYYY', label: 'DD/MM/YYYY' },
  // { value: 'MM/DD/YYYY', label: 'MM/DD/YYYY' },
  // { value: 'YYYY-MM-DD', label: 'YYYY-MM-DD' },
];

const TIME_FORMAT_OPTIONS: readonly FormSelect<TimeFormatValue>[] = [
  // { value: 'TwelveHour', label: '12 hour' },
  // { value: 'TwentyFourHour', label: '24 hour' },
];

const NUMBER_FORMAT_OPTIONS: readonly FormSelect<NumberFormatValue>[] = [
  // { value: 'OneTwoThreeCommaFourFiveSixPointSevenEight', label: '123,456.78' },
  // { value: 'OneTwoThreePointFourFiveSixCommaSevenEight', label: '123.456,78' },
];

const FISCAL_YEAR_OPTIONS: readonly FormSelect<FiscalYearConventionValue>[] = [
  // { value: 'CalendarYear', label: 'Calendar Year (Jan-Dec)' },
  // { value: 'AprilToMarch', label: 'April - March' },
  // { value: 'JulyToJune', label: 'July - June' },
];

const LICENSE_TYPE_OPTIONS: readonly FormSelect<OrganizationLicenseType>[] = [
  // { value: 'Trial', label: 'Trial' },
  // { value: 'Paid', label: 'Paid' },
];

const LOCALIZATION_DEFAULTS: readonly CountryLocalizationDefaults[] = [
  {
    countryId: 'IN',
    timeZone: { id: 'asia-kolkata', label: 'India Standard Time', secondaryLabel: 'Asia/Kolkata' },
    currency: { id: 'inr', label: 'Indian Rupee', secondaryLabel: 'INR' },
    defaultLanguage: { id: 'en-in', label: 'English', secondaryLabel: 'en-IN' },
    dateFormat: 'DD/MM/YYYY',
    timeFormat: 'TwelveHour',
    numberFormat: 'OneTwoThreeCommaFourFiveSixPointSevenEight',
    fiscalYearConvention: 'AprilToMarch',
  },
  {
    countryId: 'US',
    timeZone: { id: 'america-new-york', label: 'Eastern Time', secondaryLabel: 'America/New_York' },
    currency: { id: 'usd', label: 'US Dollar', secondaryLabel: 'USD' },
    defaultLanguage: { id: 'en-us', label: 'English', secondaryLabel: 'en-US' },
    dateFormat: 'MM/DD/YYYY',
    timeFormat: 'TwelveHour',
    numberFormat: 'OneTwoThreeCommaFourFiveSixPointSevenEight',
    fiscalYearConvention: 'CalendarYear',
  },
];

@Injectable()
export class OrganizationOnboardingService {
  private readonly countryService = inject(CountryService);
  private readonly currencyService = inject(CurrencyService);
  private readonly languageService = inject(LanguageService);
  private readonly timezoneService = inject(TimezoneService);

  searchOrganizationTypes(term: string | null, limit = 10): Observable<readonly OnboardingLookupValue[]> {
    return of(this.filterLookupValues(ORGANIZATION_TYPE_OPTIONS, term, limit));
  }

  resolveOrganizationType(id: string): Observable<OnboardingLookupValue | null> {
    return of(ORGANIZATION_TYPE_OPTIONS.find(option => option.id === id) ?? null);
  }

  searchIndustries(term: string | null, limit = 10): Observable<readonly OnboardingLookupValue[]> {
    return of(this.filterLookupValues(INDUSTRY_OPTIONS, term, limit));
  }

  resolveIndustry(id: string): Observable<OnboardingLookupValue | null> {
    return of(INDUSTRY_OPTIONS.find(option => option.id === id) ?? null);
  }

  searchRegistrationCountries(term: string | null, limit = 10): Observable<readonly CountryLookupDto[]> {
    return this.countryService.autocomplete(term ?? '', limit);
  }

  resolveCountry(id: string): Observable<CountryLookupDto | null> {
    return this.countryService.getCountryById(id).pipe(
      map(country => ({ id: country.id, iso2: country.iso2, name: country.name }))
    );
  }

  searchTimezones(term: string | null, limit = 10): Observable<readonly TimezoneLookupDto[]> {
    return this.timezoneService.autocomplete(term, limit);
  }

  resolveTimezone(id: string): Observable<TimezoneLookupDto | null> {
    return this.timezoneService.getById(id).pipe(
      map(timezone => ({ id: timezone.id, ianaId: timezone.ianaId, displayName: timezone.displayName }))
    );
  }

  searchCurrencies(term: string | null, limit = 10): Observable<readonly CurrencyLookupDto[]> {
    return this.currencyService.autocomplete(term, limit);
  }

  resolveCurrency(id: string): Observable<CurrencyLookupDto | null> {
    return this.currencyService.getCurrencyById(id).pipe(
      map(currency => ({ id: currency.id, code: currency.code, name: currency.name, symbol: currency.symbol }))
    );
  }

  searchLanguages(term: string | null, limit = 10): Observable<readonly LanguageLookupDto[]> {
    return this.languageService.autocomplete(term, limit);
  }

  resolveLanguage(id: string): Observable<LanguageLookupDto | null> {
    return this.languageService.getById(id).pipe(
      map(language => ({
        id: language.id,
        code: language.code,
        name: language.name,
        nativeName: language.nativeName,
        isRightToLeft: language.isRightToLeft,
      }))
    );
  }
loadLanguageOptions(limit = 50):readonly FormSelect<DateFormatValue>[] {
    return DATE_FORMAT_OPTIONS;
  }
  // loadLanguageOptions(limit = 50): Observable<readonly FormSelect<string>[]> {
  //   // return this.languageService.autocomplete('', limit).pipe(
  //   //   map(items => items.map(item => ({
  //   //     value: item.id,
  //   //     label: `${item.code} - ${item.name}`,
  //   //   })))
  //   // );
  // }

  getDateFormatOptions(): readonly FormSelect<DateFormatValue>[] {
    return DATE_FORMAT_OPTIONS;
  }

  getTimeFormatOptions(): readonly FormSelect<TimeFormatValue>[] {
    return TIME_FORMAT_OPTIONS;
  }

  getNumberFormatOptions(): readonly FormSelect<NumberFormatValue>[] {
    return NUMBER_FORMAT_OPTIONS;
  }

  getFiscalYearOptions(): readonly FormSelect<FiscalYearConventionValue>[] {
    return FISCAL_YEAR_OPTIONS;
  }

  getLicenseTypeOptions(): readonly FormSelect<OrganizationLicenseType>[] {
    return LICENSE_TYPE_OPTIONS;
  }

  searchSubscriptionPlans(term: string | null, limit = 10): Observable<readonly OrganizationPlanLookupValue[]> {
    return of(this.filterLookupValues(SUBSCRIPTION_PLAN_OPTIONS, term, limit));
  }

  resolveSubscriptionPlan(id: string): Observable<OrganizationPlanLookupValue | null> {
    return of(SUBSCRIPTION_PLAN_OPTIONS.find(option => option.id === id) ?? null);
  }

  getPlanDefaults(planId: string): Observable<OrganizationPlanDefaults | null> {
    return of(PLAN_DEFAULTS.find(item => item.plan.id === planId) ?? null);
  }

  getCountryLocalizationDefaults(countryIso2: string | null): Observable<CountryLocalizationDefaults | null> {
    if (!countryIso2?.trim()) {
      return of(null);
    }

    return of(LOCALIZATION_DEFAULTS.find(item => item.countryId === countryIso2.trim().toUpperCase()) ?? null);
  }

  loadDraft(): Observable<OrganizationOnboardingDraft | null> {
    try {
      const rawDraft = sessionStorage.getItem(ORGANIZATION_ONBOARDING_DRAFT_KEY);

      if (!rawDraft) {
        return of(null);
      }

      const parsedDraft = JSON.parse(rawDraft) as Partial<OrganizationOnboardingDraft>;

      if (!this.isValidDraft(parsedDraft)) {
        sessionStorage.removeItem(ORGANIZATION_ONBOARDING_DRAFT_KEY);
        return of(null);
      }

      return of(parsedDraft);
    } catch (error) {
      sessionStorage.removeItem(ORGANIZATION_ONBOARDING_DRAFT_KEY);
      return throwError(() => error);
    }
  }

  saveDraft(draft: OrganizationOnboardingDraft): Observable<void> {
    try {
      sessionStorage.setItem(ORGANIZATION_ONBOARDING_DRAFT_KEY, JSON.stringify(draft));
      return of(void 0);
    } catch (error) {
      return throwError(() => error);
    }
  }

  clearDraft(): Observable<void> {
    try {
      sessionStorage.removeItem(ORGANIZATION_ONBOARDING_DRAFT_KEY);
      return of(void 0);
    } catch (error) {
      return throwError(() => error);
    }
  }

  provisionOrganization(_request: OrganizationProvisioningRequest): Observable<OrganizationProvisioningResult> {
    return of({
      status: 'not-configured',
      message: 'Provisioning is not configured yet for organization onboarding.',
    });
  }

  private filterLookupValues<TValue extends OnboardingLookupValue>(
    source: readonly TValue[],
    term: string | null,
    limit: number,
  ): readonly TValue[] {
    const normalizedTerm = term?.trim().toLowerCase() ?? '';

    return source
      .filter(option => {
        if (!normalizedTerm) {
          return true;
        }

        return [option.label, option.secondaryLabel]
          .filter((value): value is string => !!value)
          .some(value => value.toLowerCase().includes(normalizedTerm));
      })
      .slice(0, Math.max(1, limit));
  }

  private isValidDraft(value: Partial<OrganizationOnboardingDraft>): value is OrganizationOnboardingDraft {
    return (
      value.schemaVersion === 1 &&
      typeof value.currentStepIndex === 'number' &&
      Array.isArray(value.completedStepIndexes) &&
      typeof value.savedAt === 'string'
    );
  }
}