import { DataSource, DataSourceOptions } from 'typeorm';
import * as path from 'node:path';
import * as fs from 'node:fs';
import { AppConfig } from '../config/configuration';
import { User } from './tenant/entities/user.entity';
import { Role } from './tenant/entities/role.entity';
import { Permission } from './tenant/entities/permission.entity';
import { RolePermission } from './tenant/entities/role-permission.entity';
import { UserRole } from './tenant/entities/user-role.entity';
import { Office } from './tenant/entities/office.entity';
import { Branch } from './tenant/entities/branch.entity';
import { Member } from './tenant/entities/member.entity';
import { MemberFamily } from './tenant/entities/member-family.entity';
import { Lookup } from './tenant/entities/lookup.entity';
import { DartaChalani } from './tenant/entities/darta-chalani.entity';
import { Application } from './tenant/entities/application.entity';
import { ApplicantSaving } from './tenant/entities/applicant-saving.entity';
import { ApplicantIncome } from './tenant/entities/applicant-income.entity';
import { ApplicantCharge } from './tenant/entities/applicant-charge.entity';
import { Guarantor } from './tenant/entities/guarantor.entity';
import { SavingsAccount } from './tenant/entities/savings-account.entity';
import { SavingsTransaction } from './tenant/entities/savings-transaction.entity';
import { LoanAccount } from './tenant/entities/loan-account.entity';
import { LoanPayment } from './tenant/entities/loan-payment.entity';
import { Task } from './tenant/entities/task.entity';
import { CrmLead } from './tenant/entities/crm-lead.entity';
import { Auction } from './tenant/entities/auction.entity';
import { LetterTemplate } from './tenant/entities/letter-template.entity';
import { Minute } from './tenant/entities/minute.entity';
import { Document } from './tenant/entities/document.entity';
import { CooperativeSettings } from './tenant/entities/cooperative-settings.entity';
import { DepositAccount } from './tenant/entities/deposit-account.entity';
import { Blacklist } from './tenant/entities/blacklist.entity';
import { ActivityLog } from './tenant/entities/activity-log.entity';
import { TaketaPatra } from './tenant/entities/taketa-patra.entity';
import { CreditRenew } from './tenant/entities/credit-renew.entity';
import { Share } from './tenant/entities/share.entity';
import { AccountingVoucher } from './tenant/entities/accounting-voucher.entity';
import { BoardMember } from './tenant/entities/board-member.entity';
import { Center } from './tenant/entities/center.entity';
import { Group } from './tenant/entities/group.entity';
import { StaffPosition } from './tenant/entities/staff-position.entity';
import { Insurance } from './tenant/entities/insurance.entity';
import { DocumentType } from './tenant/entities/document-type.entity';
import { Valuator } from './tenant/entities/valuator.entity';
import { NewspaperPublish } from './tenant/entities/newspaper-publish.entity';
import { BusinessUnit } from './tenant/entities/business-unit.entity';
import { Department } from './tenant/entities/department.entity';
import { CommitteeGroup } from './tenant/entities/committee-group.entity';
import { CreditAnalysisTitle } from './tenant/entities/credit-analysis-title.entity';
import { CreditAnalysisOption } from './tenant/entities/credit-analysis-option.entity';
import { OldCreditAnalysis } from './tenant/entities/old-credit-analysis.entity';
import { NewCreditAnalysis } from './tenant/entities/new-credit-analysis.entity';
import { MortgageAppraisal } from './tenant/entities/mortgage-appraisal.entity';
import { MortgageAppraisalLand } from './tenant/entities/mortgage-appraisal-land.entity';
import { AdditionalWithholding } from './tenant/entities/additional-withholding.entity';
import { WithholdingKitta } from './tenant/entities/withholding-kitta.entity';
import { CollateralHome } from './tenant/entities/collateral-home.entity';
import { CollateralVehicle } from './tenant/entities/collateral-vehicle.entity';
import { CollateralAnshiyar } from './tenant/entities/collateral-anshiyar.entity';
import { CollateralLandOwner } from './tenant/entities/collateral-land-owner.entity';
import { CollateralSavings } from './tenant/entities/collateral-savings.entity';
import { CollateralFixedDeposit } from './tenant/entities/collateral-fixed-deposit.entity';
import { CollateralMicrofinance } from './tenant/entities/collateral-microfinance.entity';
import { CollateralGeneral } from './tenant/entities/collateral-general.entity';
import { ApplicationFile } from './tenant/entities/application-file.entity';
import { ApplicationComment } from './tenant/entities/application-comment.entity';
import { ApplicationStatusLog } from './tenant/entities/application-status-log.entity';
import { ApplicationRecommendation } from './tenant/entities/application-recommendation.entity';
import { ApplicationForward } from './tenant/entities/application-forward.entity';
import { ApplicationForwardUser } from './tenant/entities/application-forward-user.entity';
import { LoanTitle } from './tenant/entities/loan-title.entity';
import { LoanPurpose } from './tenant/entities/loan-purpose.entity';
import { MemberIncome } from './tenant/entities/member-income.entity';
import { MemberBusinessIncome } from './tenant/entities/member-business-income.entity';
import { MemberFinancial } from './tenant/entities/member-financial.entity';
import { ApplicantBusinessIncome } from './tenant/entities/applicant-business-income.entity';
import { ApplicantPayableInstitution } from './tenant/entities/applicant-payable-institution.entity';
import { ApplicantFinancialTransaction } from './tenant/entities/applicant-financial-transaction.entity';
import { ApplicationRelation } from './tenant/entities/application-relation.entity';
import { ExternalGuarantor } from './tenant/entities/external-guarantor.entity';

export const TENANT_ENTITIES = [
  User,
  Role,
  Permission,
  RolePermission,
  UserRole,
  Office,
  Branch,
  Member,
  MemberFamily,
  Lookup,
  DartaChalani,
  Application,
  ApplicantSaving,
  ApplicantIncome,
  ApplicantCharge,
  Guarantor,
  SavingsAccount,
  SavingsTransaction,
  LoanAccount,
  LoanPayment,
  Task,
  CrmLead,
  Auction,
  LetterTemplate,
  Minute,
  Document,
  CooperativeSettings,
  DepositAccount,
  Blacklist,
  ActivityLog,
  TaketaPatra,
  CreditRenew,
  Share,
  AccountingVoucher,
  BoardMember,
  Center,
  Group,
  StaffPosition,
  Insurance,
  DocumentType,
  Valuator,
  NewspaperPublish,
  BusinessUnit,
  Department,
  CommitteeGroup,
  CreditAnalysisTitle,
  CreditAnalysisOption,
  OldCreditAnalysis,
  NewCreditAnalysis,
  MortgageAppraisal,
  MortgageAppraisalLand,
  AdditionalWithholding,
  WithholdingKitta,
  CollateralHome,
  CollateralVehicle,
  CollateralAnshiyar,
  CollateralLandOwner,
  CollateralSavings,
  CollateralFixedDeposit,
  CollateralMicrofinance,
  CollateralGeneral,
  ApplicationFile,
  ApplicationComment,
  ApplicationStatusLog,
  ApplicationRecommendation,
  ApplicationForward,
  ApplicationForwardUser,
  LoanTitle,
  LoanPurpose,
  MemberIncome,
  MemberBusinessIncome,
  MemberFinancial,
  ApplicantBusinessIncome,
  ApplicantPayableInstitution,
  ApplicantFinancialTransaction,
  ApplicationRelation,
  ExternalGuarantor,
];

export function buildTenantDataSourceOptions(
  cfg: AppConfig,
  tenantSubdomain: string,
): DataSourceOptions {
  const common = {
    entities: TENANT_ENTITIES,
    synchronize: true,
    logging: false,
  } as const;

  if (cfg.db.driver === 'mysql') {
    return {
      type: 'mysql',
      host: cfg.db.mysql.host,
      port: cfg.db.mysql.port,
      username: cfg.db.mysql.user,
      password: cfg.db.mysql.password,
      database: cfg.db.mysql.tenantDbPrefix + tenantSubdomain,
      charset: 'utf8mb4',
      ...common,
    };
  }

  if (cfg.db.driver === 'postgres') {
    return {
      type: 'postgres',
      host:     cfg.db.postgres.host,
      port:     cfg.db.postgres.port,
      username: cfg.db.postgres.user,
      password: cfg.db.postgres.password,
      database: cfg.db.postgres.database,
      schema:   cfg.db.postgres.tenantSchemaPrefix + tenantSubdomain,
      ...common,
    };
  }

  // SQLite (sql.js): separate file per tenant
  const tenantDir = path.resolve(
    process.cwd(),
    cfg.db.sqlite.dataDir,
    cfg.db.sqlite.tenantDir,
  );
  if (!fs.existsSync(tenantDir)) fs.mkdirSync(tenantDir, { recursive: true });
  return {
    type: 'sqljs',
    location: path.join(tenantDir, `${tenantSubdomain}.sqlite`),
    autoSave: true,
    useLocalForage: false,
    ...common,
  };
}
