import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { TenantConnectionService } from '../../database/tenant-connection.service';
import { Lookup } from '../../database/tenant/entities/lookup.entity';
import { CreateLookupDto, UpdateLookupDto } from './master.dto';

const DEFAULT_LOOKUPS: Array<Omit<Lookup, 'id' | 'createdAt' | 'updatedAt'>> = [
  // ─── ऋणको उद्देश्य (Loan Purpose) ──────────────────────────────────────────
  { type: 'loan_purpose', code: 'agricultural',   label: 'Agricultural',          labelNe: 'कृषि',             order: 1,  active: true },
  { type: 'loan_purpose', code: 'business',       label: 'Business',              labelNe: 'व्यापार',           order: 2,  active: true },
  { type: 'loan_purpose', code: 'education',      label: 'Education',             labelNe: 'शिक्षा',            order: 3,  active: true },
  { type: 'loan_purpose', code: 'home',           label: 'Home Construction',     labelNe: 'घर निर्माण',        order: 4,  active: true },
  { type: 'loan_purpose', code: 'vehicle',        label: 'Vehicle',               labelNe: 'सवारी साधन',        order: 5,  active: true },
  { type: 'loan_purpose', code: 'personal',       label: 'Personal',              labelNe: 'व्यक्तिगत',         order: 6,  active: true },
  { type: 'loan_purpose', code: 'microfinance',   label: 'Microfinance',          labelNe: 'लघुवित्त',          order: 7,  active: true },
  { type: 'loan_purpose', code: 'land_purchase',  label: 'Land Purchase',         labelNe: 'जग्गा खरिद',        order: 8,  active: true },
  { type: 'loan_purpose', code: 'foreign_employ', label: 'Foreign Employment',    labelNe: 'वैदेशिक रोजगार',    order: 9,  active: true },
  { type: 'loan_purpose', code: 'livestock',      label: 'Livestock/Poultry',     labelNe: 'पशुपालन/कुखुरापालन',order: 10, active: true },

  // ─── ऋणको शीर्षक (Loan Title) — meta stores interestRate ───────────────────
  { type: 'loan_title', code: 'gold_loan',        label: 'Gold Loan',             labelNe: 'सुन धितो ऋण',       order: 1, active: true, meta: JSON.stringify({ interestRate: 11 }) },
  { type: 'loan_title', code: 'real_estate',      label: 'Real Estate Loan',      labelNe: 'घर जग्गा ऋण',       order: 2, active: true, meta: JSON.stringify({ interestRate: 12 }) },
  { type: 'loan_title', code: 'salary_loan',      label: 'Salary Loan',           labelNe: 'तलब ऋण',            order: 3, active: true, meta: JSON.stringify({ interestRate: 10 }) },
  { type: 'loan_title', code: 'business_loan',    label: 'Business Loan',         labelNe: 'व्यापार ऋण',        order: 4, active: true, meta: JSON.stringify({ interestRate: 13 }) },
  { type: 'loan_title', code: 'personal_loan',    label: 'Personal Loan',         labelNe: 'व्यक्तिगत ऋण',      order: 5, active: true, meta: JSON.stringify({ interestRate: 14 }) },
  { type: 'loan_title', code: 'foreign_employ',   label: 'Foreign Employment Loan',labelNe: 'वैदेशिक रोजगार ऋण', order: 6, active: true, meta: JSON.stringify({ interestRate: 11 }) },
  { type: 'loan_title', code: 'vehicle_loan',     label: 'Vehicle Loan',          labelNe: 'सवारी साधन ऋण',     order: 7, active: true, meta: JSON.stringify({ interestRate: 12 }) },
  { type: 'loan_title', code: 'agriculture_loan', label: 'Agriculture Loan',      labelNe: 'कृषि ऋण',           order: 8, active: true, meta: JSON.stringify({ interestRate: 9 }) },

  // ─── बचतको प्रकार (Saving Type) ─────────────────────────────────────────────
  { type: 'saving_type', code: 'regular',         label: 'Regular Saving',        labelNe: 'साधारण बचत',        order: 1, active: true, meta: JSON.stringify({ interestRate: 5 }) },
  { type: 'saving_type', code: 'fixed_deposit',   label: 'Fixed Deposit',         labelNe: 'मुद्दती बचत',       order: 2, active: true, meta: JSON.stringify({ interestRate: 9 }) },
  { type: 'saving_type', code: 'compulsory',      label: 'Compulsory Saving',     labelNe: 'अनिवार्य बचत',       order: 3, active: true, meta: JSON.stringify({ interestRate: 6 }) },
  { type: 'saving_type', code: 'recurring',       label: 'Recurring Deposit',     labelNe: 'आवधिक बचत',         order: 4, active: true, meta: JSON.stringify({ interestRate: 8 }) },
  { type: 'saving_type', code: 'sanchi',          label: 'Sanchi (Share)',        labelNe: 'सञ्चि बचत',         order: 5, active: true, meta: JSON.stringify({ interestRate: 7 }) },
  { type: 'saving_type', code: 'special',         label: 'Special Saving',        labelNe: 'विशेष बचत',         order: 6, active: true, meta: JSON.stringify({ interestRate: 7.5 }) },

  // ─── आयको स्रोत (Income Source) ─────────────────────────────────────────────
  { type: 'income_source', code: 'salary',        label: 'Salary/Service',        labelNe: 'तलब/नोकरी',         order: 1, active: true },
  { type: 'income_source', code: 'business',      label: 'Business Income',       labelNe: 'व्यापार आय',         order: 2, active: true },
  { type: 'income_source', code: 'agriculture',   label: 'Agriculture Income',    labelNe: 'कृषि आय',            order: 3, active: true },
  { type: 'income_source', code: 'pension',       label: 'Pension',               labelNe: 'निवृत्ति भरण',       order: 4, active: true },
  { type: 'income_source', code: 'rental',        label: 'Rental Income',         labelNe: 'भाडा आय',            order: 5, active: true },
  { type: 'income_source', code: 'remittance',    label: 'Remittance',            labelNe: 'रेमिट्यान्स',       order: 6, active: true },
  { type: 'income_source', code: 'other',         label: 'Other Income',          labelNe: 'अन्य आय',            order: 7, active: true },

  // ─── धितोको प्रकार (Collateral Type) ────────────────────────────────────────
  { type: 'collateral_type', code: 'home',        label: 'Home/Land',             labelNe: 'घर/जग्गा',           order: 1, active: true },
  { type: 'collateral_type', code: 'vehicle',     label: 'Vehicle',               labelNe: 'सवारी साधन',         order: 2, active: true },
  { type: 'collateral_type', code: 'gold',        label: 'Gold/Silver',           labelNe: 'सुन/चाँदी',          order: 3, active: true },
  { type: 'collateral_type', code: 'salary',      label: 'Salary Assignment',     labelNe: 'तलब असाइनमेन्ट',    order: 4, active: true },
  { type: 'collateral_type', code: 'fd',          label: 'Fixed Deposit',         labelNe: 'मुद्दती बचत',        order: 5, active: true },
  { type: 'collateral_type', code: 'anshiyar',    label: 'Anshiyar (Share)',      labelNe: 'अंशियार',            order: 6, active: true },
  { type: 'collateral_type', code: 'other',       label: 'Other',                 labelNe: 'अन्य',               order: 7, active: true },

  // ─── भुक्तानी प्रकार (Repayment Type) ────────────────────────────────────────
  { type: 'repayment_type', code: 'emi',          label: 'EMI (Equal Monthly Installment)', labelNe: 'समान मासिक किस्ता', order: 1, active: true },
  { type: 'repayment_type', code: 'bullet',       label: 'Bullet (Lump Sum)',     labelNe: 'एकमुष्ट भुक्तान',    order: 2, active: true },
  { type: 'repayment_type', code: 'quarterly',    label: 'Quarterly',             labelNe: 'त्रैमासिक',          order: 3, active: true },
  { type: 'repayment_type', code: 'semi_annual',  label: 'Semi-Annual',           labelNe: 'अर्धवार्षिक',        order: 4, active: true },
  { type: 'repayment_type', code: 'annual',       label: 'Annual',                labelNe: 'वार्षिक',             order: 5, active: true },

  // ─── पद (Staff Position) ─────────────────────────────────────────────────────
  { type: 'staff_position', code: 'chairman',     label: 'Chairman',              labelNe: 'अध्यक्ष',            order: 1, active: true },
  { type: 'staff_position', code: 'vice_chair',   label: 'Vice-Chairman',         labelNe: 'उपाध्यक्ष',          order: 2, active: true },
  { type: 'staff_position', code: 'secretary',    label: 'Secretary',             labelNe: 'सचिव',               order: 3, active: true },
  { type: 'staff_position', code: 'treasurer',    label: 'Treasurer',             labelNe: 'कोषाध्यक्ष',         order: 4, active: true },
  { type: 'staff_position', code: 'ceo',          label: 'CEO/Manager',           labelNe: 'प्रमुख कार्यकारी',   order: 5, active: true },
  { type: 'staff_position', code: 'accountant',   label: 'Accountant',            labelNe: 'लेखापाल',             order: 6, active: true },
  { type: 'staff_position', code: 'loan_officer', label: 'Loan Officer',          labelNe: 'ऋण अधिकृत',          order: 7, active: true },
  { type: 'staff_position', code: 'member_officer',label: 'Member Service Officer',labelNe: 'सदस्य सेवा अधिकृत', order: 8, active: true },
  { type: 'staff_position', code: 'clerk',        label: 'Clerk',                 labelNe: 'किरानी',             order: 9, active: true },

  // ─── समूह/केन्द्र (Group/Center) ─────────────────────────────────────────────
  { type: 'center', code: 'main_center',          label: 'Main Center',           labelNe: 'मुख्य केन्द्र',      order: 1, active: true, meta: JSON.stringify({ address: '' }) },
  { type: 'group',  code: 'main_group',           label: 'Main Group',            labelNe: 'मुख्य समूह',         order: 1, active: true, meta: JSON.stringify({ address: '', number: '1', centerId: '' }) },

  // ─── कागजात प्रकार (Document Type) ──────────────────────────────────────────
  { type: 'document_type', code: 'citizenship',   label: 'Citizenship Certificate',labelNe: 'नागरिकता प्रमाणपत्र', order: 1, active: true },
  { type: 'document_type', code: 'passport',      label: 'Passport',              labelNe: 'राहदानी',            order: 2, active: true },
  { type: 'document_type', code: 'voter_id',      label: 'Voter ID Card',         labelNe: 'मतदाता परिचयपत्र',   order: 3, active: true },
  { type: 'document_type', code: 'driving_lic',   label: "Driver's License",      labelNe: 'सवारी चालक अनुमतिपत्र', order: 4, active: true },
  { type: 'document_type', code: 'pan',           label: 'PAN Card',              labelNe: 'स्थायी लेखा नम्बर',  order: 5, active: true },
  { type: 'document_type', code: 'land_cert',     label: 'Land Certificate (Lalpurja)', labelNe: 'जग्गाधनी प्रमाणपत्र', order: 6, active: true },
  { type: 'document_type', code: 'income_cert',   label: 'Income Certificate',    labelNe: 'आय प्रमाणपत्र',       order: 7, active: true },
  { type: 'document_type', code: 'photo',         label: 'Photograph',            labelNe: 'फोटो',               order: 8, active: true },

  // ─── बीमा कम्पनी (Insurance Company) ─────────────────────────────────────────
  { type: 'insurance',     code: 'national_life', label: 'National Life Insurance', labelNe: 'राष्ट्रिय जीवन बीमा', order: 1, active: true, meta: JSON.stringify({ phone: '', address: 'Kathmandu' }) },
  { type: 'insurance',     code: 'nlic',          label: 'Nepal Life Insurance Co.', labelNe: 'नेपाल जीवन बीमा',  order: 2, active: true, meta: JSON.stringify({ phone: '', address: 'Kathmandu' }) },
  { type: 'insurance',     code: 'shikhar',       label: 'Shikhar Insurance Co.', labelNe: 'शिखर बीमा',          order: 3, active: true, meta: JSON.stringify({ phone: '', address: 'Kathmandu' }) },
  { type: 'insurance',     code: 'himalayan',     label: 'Himalayan General Ins.', labelNe: 'हिमालयन बीमा',       order: 4, active: true, meta: JSON.stringify({ phone: '', address: 'Kathmandu' }) },

  // ─── लघुवित्त कार्यक्रम (Microfinance Program) ───────────────────────────────
  { type: 'microfinance_program', code: 'jlg',    label: 'Joint Liability Group (JLG)', labelNe: 'संयुक्त दायित्व समूह', order: 1, active: true },
  { type: 'microfinance_program', code: 'iga',    label: 'Income Generating Activity', labelNe: 'आय आर्जन कार्यक्रम', order: 2, active: true },
  { type: 'microfinance_program', code: 'shg',    label: 'Self Help Group (SHG)',  labelNe: 'स्व-सहायता समूह',    order: 3, active: true },

  // ─── मालपोत कार्यालय (Malpot Office) ─────────────────────────────────────────
  { type: 'malpot_office', code: 'ktm_malpot',    label: 'Kathmandu Malpot',      labelNe: 'काठमाडौं मालपोत',    order: 1, active: true },
  { type: 'malpot_office', code: 'lalitpur_malpot',label: 'Lalitpur Malpot',      labelNe: 'ललितपुर मालपोत',     order: 2, active: true },
  { type: 'malpot_office', code: 'bhaktapur_malpot',label: 'Bhaktapur Malpot',   labelNe: 'भक्तपुर मालपोत',     order: 3, active: true },
  { type: 'malpot_office', code: 'other_malpot',  label: 'Other District Malpot', labelNe: 'अन्य जिल्ला मालपोत', order: 4, active: true },

  // ─── सर्वेक्षण कार्यालय (Surveyor Office) ─────────────────────────────────────
  { type: 'surveyor_office', code: 'ktm_survey',  label: 'Kathmandu Survey',      labelNe: 'काठमाडौं सर्वेक्षण', order: 1, active: true },
  { type: 'surveyor_office', code: 'other_survey',label: 'Other District Survey', labelNe: 'अन्य जिल्ला सर्वेक्षण', order: 2, active: true },

  // ─── यातायात कार्यालय (Yatayat Office) ──────────────────────────────────────
  { type: 'yatayat_office', code: 'bagmati_yatayat', label: 'Bagmati Transport Office', labelNe: 'बागमती यातायात',  order: 1, active: true },
  { type: 'yatayat_office', code: 'other_yatayat',   label: 'Other Transport Office',   labelNe: 'अन्य यातायात',    order: 2, active: true },

  // ─── सवारी साधन प्रदायक (Vehicle Provider) ────────────────────────────────────
  { type: 'vehicle_provider', code: 'hyundai',    label: 'Hyundai',               labelNe: 'हुन्डाई',            order: 1, active: true },
  { type: 'vehicle_provider', code: 'toyota',     label: 'Toyota',                labelNe: 'टोयोटा',             order: 2, active: true },
  { type: 'vehicle_provider', code: 'suzuki',     label: 'Suzuki',                labelNe: 'सुजुकी',             order: 3, active: true },
  { type: 'vehicle_provider', code: 'honda',      label: 'Honda',                 labelNe: 'होन्डा',             order: 4, active: true },
  { type: 'vehicle_provider', code: 'other',      label: 'Other',                 labelNe: 'अन्य',               order: 5, active: true },

  // ─── व्यापार इकाई (Business Unit) ────────────────────────────────────────────
  { type: 'business_unit', code: 'head_office',   label: 'Head Office',           labelNe: 'केन्द्रीय कार्यालय', order: 1, active: true },
  { type: 'business_unit', code: 'branch',        label: 'Branch',                labelNe: 'शाखा',               order: 2, active: true },
  { type: 'business_unit', code: 'sub_branch',    label: 'Sub-Branch',            labelNe: 'उपशाखा',             order: 3, active: true },

  // ─── विभाग (Department) ───────────────────────────────────────────────────────
  { type: 'department', code: 'admin',            label: 'Administration',        labelNe: 'प्रशासन',            order: 1, active: true },
  { type: 'department', code: 'accounts',         label: 'Accounts',              labelNe: 'लेखा',               order: 2, active: true },
  { type: 'department', code: 'credit',           label: 'Credit/Loan',           labelNe: 'ऋण विभाग',           order: 3, active: true },
  { type: 'department', code: 'savings',          label: 'Savings',               labelNe: 'बचत विभाग',          order: 4, active: true },
  { type: 'department', code: 'it',               label: 'IT',                    labelNe: 'सूचना प्रविधि',      order: 5, active: true },

  // ─── समिति समूह (Committee Group) ────────────────────────────────────────────
  { type: 'committee_group', code: 'boc',         label: 'Board of Directors',    labelNe: 'संचालक समिति',       order: 1, active: true },
  { type: 'committee_group', code: 'management',  label: 'Management Committee',  labelNe: 'व्यवस्थापन समिति',   order: 2, active: true },
  { type: 'committee_group', code: 'audit',       label: 'Audit Committee',       labelNe: 'लेखापरीक्षण समिति',  order: 3, active: true },
  { type: 'committee_group', code: 'credit_committee', label: 'Credit Committee', labelNe: 'ऋण समिति',           order: 4, active: true },

  // ─── पत्रिका (Newspaper) ──────────────────────────────────────────────────────
  { type: 'newspaper', code: 'gorkhapatra',       label: 'Gorkhapatra',           labelNe: 'गोरखापत्र',          order: 1, active: true },
  { type: 'newspaper', code: 'rajdhani',          label: 'Rajdhani Daily',        labelNe: 'राजधानी',            order: 2, active: true },
  { type: 'newspaper', code: 'kantipur',          label: 'Kantipur',              labelNe: 'कान्तिपुर',          order: 3, active: true },
  { type: 'newspaper', code: 'annapurna',         label: 'Annapurna Post',        labelNe: 'अन्नपूर्ण पोस्ट',   order: 4, active: true },
  { type: 'newspaper', code: 'nagarik',           label: 'Nagarik News',          labelNe: 'नागरिक',             order: 5, active: true },

  // ─── पेशा/व्यवसाय (Occupation Type) ─────────────────────────────────────────
  { type: 'occupation_type', code: 'agriculture',  label: 'Agriculture',          labelNe: 'कृषि',               order: 1, active: true },
  { type: 'occupation_type', code: 'business',     label: 'Business/Trade',       labelNe: 'व्यापार',            order: 2, active: true },
  { type: 'occupation_type', code: 'service',      label: 'Government Service',   labelNe: 'सरकारी सेवा',        order: 3, active: true },
  { type: 'occupation_type', code: 'private_job',  label: 'Private Job',          labelNe: 'निजी जागिर',         order: 4, active: true },
  { type: 'occupation_type', code: 'foreign_employ',label: 'Foreign Employment',  labelNe: 'वैदेशिक रोजगार',     order: 5, active: true },
  { type: 'occupation_type', code: 'housewife',    label: 'Housewife',            labelNe: 'गृहिणी',             order: 6, active: true },
  { type: 'occupation_type', code: 'student',      label: 'Student',              labelNe: 'विद्यार्थी',         order: 7, active: true },
  { type: 'occupation_type', code: 'other',        label: 'Other',                labelNe: 'अन्य',               order: 8, active: true },

  // ─── नाताको सम्बन्ध (Relationship Type) ─────────────────────────────────────
  { type: 'relationship_type', code: 'husband',   label: 'Husband',               labelNe: 'पति',                order: 1, active: true },
  { type: 'relationship_type', code: 'wife',      label: 'Wife',                  labelNe: 'पत्नी',              order: 2, active: true },
  { type: 'relationship_type', code: 'son',       label: 'Son',                   labelNe: 'छोरा',               order: 3, active: true },
  { type: 'relationship_type', code: 'daughter',  label: 'Daughter',              labelNe: 'छोरी',               order: 4, active: true },
  { type: 'relationship_type', code: 'father',    label: 'Father',                labelNe: 'बुवा',               order: 5, active: true },
  { type: 'relationship_type', code: 'mother',    label: 'Mother',                labelNe: 'आमा',                order: 6, active: true },
  { type: 'relationship_type', code: 'brother',   label: 'Brother',               labelNe: 'भाइ/दाइ',            order: 7, active: true },
  { type: 'relationship_type', code: 'sister',    label: 'Sister',                labelNe: 'बहिनी/दिदी',         order: 8, active: true },
  { type: 'relationship_type', code: 'other',     label: 'Other',                 labelNe: 'अन्य',               order: 9, active: true },
] as any[];

@Injectable()
export class MasterService {
  constructor(private tenantConn: TenantConnectionService) {}

  private async repo(tenantSubdomain: string) {
    const ds = await this.tenantConn.getTenantDataSource(tenantSubdomain);
    return ds.getRepository(Lookup);
  }

  async seed(tenantSubdomain: string) {
    const r = await this.repo(tenantSubdomain);
    for (const row of DEFAULT_LOOKUPS) {
      const exists = await r.findOne({ where: { type: row.type, code: row.code } });
      if (!exists) {
        await r.save(r.create(row));
      }
    }
  }

  async findByType(tenantSubdomain: string, type: string) {
    const r = await this.repo(tenantSubdomain);
    return r.find({ where: { type }, order: { order: 'ASC', label: 'ASC' } });
  }

  async findAll(tenantSubdomain: string, type?: string) {
    const r = await this.repo(tenantSubdomain);
    const qb = r.createQueryBuilder('l').orderBy('l.type').addOrderBy('l.order').addOrderBy('l.label');
    if (type) qb.where('l.type = :type', { type });
    return qb.getMany();
  }

  async findOne(tenantSubdomain: string, id: string) {
    const r = await this.repo(tenantSubdomain);
    const l = await r.findOne({ where: { id } });
    if (!l) throw new NotFoundException('Lookup not found');
    return l;
  }

  async create(tenantSubdomain: string, dto: CreateLookupDto) {
    const r = await this.repo(tenantSubdomain);
    const existing = await r.findOne({ where: { type: dto.type, code: dto.code } });
    if (existing) throw new ConflictException('Lookup with same type+code already exists');
    const l = r.create({ ...dto, order: dto.order ?? 0, active: dto.active ?? true });
    return r.save(l);
  }

  async update(tenantSubdomain: string, id: string, dto: UpdateLookupDto) {
    const r = await this.repo(tenantSubdomain);
    const l = await this.findOne(tenantSubdomain, id);
    Object.assign(l, dto);
    return r.save(l);
  }

  async remove(tenantSubdomain: string, id: string) {
    const r = await this.repo(tenantSubdomain);
    const l = await this.findOne(tenantSubdomain, id);
    await r.remove(l);
    return { ok: true };
  }

  async types(tenantSubdomain: string): Promise<string[]> {
    const r = await this.repo(tenantSubdomain);
    const rows = await r.createQueryBuilder('l').select('DISTINCT l.type', 'type').getRawMany();
    return rows.map((r: any) => r.type);
  }
}
