/**
 * Welati (Elections & Governance) Pallet Integration
 *
 * This module provides helper functions for interacting with the Welati pallet,
 * which handles:
 * - Presidential and Parliamentary Elections
 * - Speaker and Constitutional Court Elections
 * - Official Appointments (Ministers, Diwan)
 * - Collective Proposals (Parliament/Diwan voting)
 */

import type { ApiPromise } from '@pezkuwi/api';
import type { Option, Vec } from '@pezkuwi/types';
import type { AccountId, BlockNumber } from '@pezkuwi/types/interfaces';

// ============================================================================
// TYPE DEFINITIONS
// ============================================================================

export type ElectionType = 'Presidential' | 'Parliamentary' | 'SpeakerElection' | 'ConstitutionalCourt';

export type ElectionStatus = 'CandidacyPeriod' | 'CampaignPeriod' | 'VotingPeriod' | 'Completed';

export type VoteChoice = 'Aye' | 'Nay' | 'Abstain';

export type CollectiveDecisionType =
  | 'ParliamentSimpleMajority'
  | 'ParliamentSuperMajority'
  | 'ParliamentAbsoluteMajority'
  | 'ConstitutionalReview'
  | 'ConstitutionalUnanimous'
  | 'ExecutiveDecision';

export type ProposalPriority = 'Urgent' | 'High' | 'Normal' | 'Low';

export type ProposalStatus = 'Active' | 'Approved' | 'Rejected' | 'Expired' | 'Executed';

export type MinisterRole =
  | 'WezireDarayiye'    // Finance
  | 'WezireParez'       // Defense
  | 'WezireDad'         // Justice
  | 'WezireBelaw'       // Education
  | 'WezireTend'        // Health
  | 'WezireAva'         // Water Resources
  | 'WezireCand';       // Culture

export type GovernmentPosition = 'Serok' | 'SerokWeziran' | 'MeclisBaskanı';

export interface ElectionInfo {
  electionId: number;
  electionType: ElectionType;
  status: ElectionStatus;
  startBlock: number;
  candidacyEndBlock: number;
  campaignEndBlock: number;
  votingEndBlock: number;
  totalCandidates: number;
  totalVotes: number;
  turnoutPercentage: number;
  districtCount?: number;
}

export interface CandidateInfo {
  account: string;
  districtId?: number;
  registeredAt: number;
  endorsersCount: number;
  voteCount: number;
  depositPaid: string;
}

export interface ElectionResult {
  electionId: number;
  winners: string[];
  totalVotes: number;
  turnoutPercentage: number;
  finalizedAt: number;
  runoffRequired: boolean;
}

export interface ParliamentMember {
  account: string;
  electedAt: number;
  termEndsAt: number;
  votesParticipated: number;
  totalVotesEligible: number;
  participationRate: number;
  committees: string[];
}

export interface CollectiveProposal {
  proposalId: number;
  proposer: string;
  title: string;
  description: string;
  proposedAt: number;
  votingStartsAt: number;
  expiresAt: number;
  decisionType: CollectiveDecisionType;
  status: ProposalStatus;
  ayeVotes: number;
  nayVotes: number;
  abstainVotes: number;
  threshold: number;
  votesCast: number;
  priority: ProposalPriority;
}

export interface AppointmentProcess {
  processId: number;
  nominee: string;
  role: string;
  nominator: string;
  justification: string;
  status: 'Pending' | 'Approved' | 'Rejected';
  createdAt: number;
  deadline: number;
}

export interface GovernanceMetrics {
  totalElectionsHeld: number;
  activeElections: number;
  parliamentSize: number;
  diwanSize: number;
  activeProposals: number;
  totalProposalsSubmitted: number;
  averageTurnout: number;
}

// ============================================================================
// QUERY FUNCTIONS (Read-only)
// ============================================================================

/**
 * Get current government officials
 */
export async function getCurrentOfficials(api: ApiPromise): Promise<{
  serok?: string;
  serokWeziran?: string;
  meclisBaskanı?: string;
}> {
  // Check if welati pallet exists
  if (!api.query.welati?.currentOfficials) {
    return {};
  }

  const [serok, serokWeziran, speaker] = await Promise.all([
    api.query.welati.currentOfficials('Serok'),
    api.query.welati.currentOfficials('SerokWeziran'),
    api.query.welati.currentOfficials('MeclisBaskanı'),
  ]);

  return {
    serok: serok.isSome ? (serok.unwrap() as any).toString() : undefined,
    serokWeziran: serokWeziran.isSome ? (serokWeziran.unwrap() as any).toString() : undefined,
    meclisBaskanı: speaker.isSome ? (speaker.unwrap() as any).toString() : undefined,
  };
}

/**
 * Get current cabinet ministers
 */
export async function getCurrentMinisters(api: ApiPromise): Promise<Record<MinisterRole, string | undefined>> {
  // Check if welati pallet exists
  if (!api.query.welati?.currentMinisters) {
    return {} as Record<MinisterRole, string | undefined>;
  }

  const roles: MinisterRole[] = [
    'WezireDarayiye',
    'WezireParez',
    'WezireDad',
    'WezireBelaw',
    'WezireTend',
    'WezireAva',
    'WezireCand',
  ];

  const ministers = await Promise.all(
    roles.map(role => api.query.welati.currentMinisters(role))
  );

  const result: Record<string, string | undefined> = {};
  roles.forEach((role, index) => {
    result[role] = ministers[index].isSome ? (ministers[index].unwrap() as any).toString() : undefined;
  });

  return result as Record<MinisterRole, string | undefined>;
}

/**
 * Get parliament members list
 */
export async function getParliamentMembers(api: ApiPromise): Promise<ParliamentMember[]> {
  // Check if welati pallet exists
  if (!api.query.welati?.parliamentMembers) {
    return [];
  }

  const members = await api.query.welati.parliamentMembers();

  if (!members || members.isEmpty) {
    return [];
  }

  const memberList: ParliamentMember[] = [];
  const accountIds = members.toJSON() as string[];

  for (const accountId of accountIds) {
    // In a real implementation, fetch detailed member info
    // For now, return basic structure
    memberList.push({
      account: accountId,
      electedAt: 0,
      termEndsAt: 0,
      votesParticipated: 0,
      totalVotesEligible: 0,
      participationRate: 0,
      committees: [],
    });
  }

  return memberList;
}

/**
 * Get Diwan (Constitutional Court) members
 */
export async function getDiwanMembers(api: ApiPromise): Promise<string[]> {
  // Check if welati pallet exists
  if (!api.query.welati?.diwanMembers) {
    return [];
  }

  const members = await api.query.welati.diwanMembers();

  if (!members || members.isEmpty) {
    return [];
  }

  return (members.toJSON() as string[]) || [];
}

/**
 * Get active elections
 */
export async function getActiveElections(api: ApiPromise): Promise<ElectionInfo[]> {
  // Check if welati pallet exists
  if (!api.query.welati?.nextElectionId) {
    return [];
  }

  const nextId = await api.query.welati.nextElectionId();
  const currentId = (nextId.toJSON() as number) || 0;

  const elections: ElectionInfo[] = [];

  // Query last 10 elections
  for (let i = Math.max(0, currentId - 10); i < currentId; i++) {
    const election = await api.query.welati.activeElections(i);

    if (election.isSome) {
      const data = (election.unwrap() as any).toJSON() as any;

      elections.push({
        electionId: i,
        electionType: data.electionType as ElectionType,
        status: data.status as ElectionStatus,
        startBlock: data.startBlock,
        candidacyEndBlock: data.candidacyEndBlock,
        campaignEndBlock: data.campaignEndBlock,
        votingEndBlock: data.votingEndBlock,
        totalCandidates: data.totalCandidates || 0,
        totalVotes: data.totalVotes || 0,
        turnoutPercentage: data.turnoutPercentage || 0,
        districtCount: data.districtCount,
      });
    }
  }

  return elections.filter(e => e.status !== 'Completed');
}

/**
 * Get election by ID
 */
export async function getElectionById(api: ApiPromise, electionId: number): Promise<ElectionInfo | null> {
  // Check if welati pallet exists
  if (!api.query.welati?.activeElections) {
    return null;
  }

  const election = await api.query.welati.activeElections(electionId);

  if (election.isNone) {
    return null;
  }

  const data = (election.unwrap() as any).toJSON() as any;

  return {
    electionId,
    electionType: data.electionType as ElectionType,
    status: data.status as ElectionStatus,
    startBlock: data.startBlock,
    candidacyEndBlock: data.candidacyEndBlock,
    campaignEndBlock: data.campaignEndBlock,
    votingEndBlock: data.votingEndBlock,
    totalCandidates: data.totalCandidates || 0,
    totalVotes: data.totalVotes || 0,
    turnoutPercentage: data.turnoutPercentage || 0,
    districtCount: data.districtCount,
  };
}

/**
 * Get candidates for an election
 */
export async function getElectionCandidates(
  api: ApiPromise,
  electionId: number
): Promise<CandidateInfo[]> {
  // Check if welati pallet exists
  if (!api.query.welati?.electionCandidates) {
    return [];
  }

  const entries = await api.query.welati.electionCandidates.entries(electionId);

  const candidates: CandidateInfo[] = [];

  for (const [key, value] of entries) {
    const data = value.toJSON() as any;
    const account = (key.args[1] as unknown as AccountId).toString();

    candidates.push({
      account,
      districtId: data.districtId,
      registeredAt: data.registeredAt,
      endorsersCount: data.endorsers?.length || 0,
      voteCount: data.voteCount || 0,
      depositPaid: data.depositPaid?.toString() || '0',
    });
  }

  return candidates.sort((a, b) => b.voteCount - a.voteCount);
}

/**
 * Check if user has voted in an election
 */
export async function hasVoted(
  api: ApiPromise,
  electionId: number,
  voterAddress: string
): Promise<boolean> {
  // Check if welati pallet exists
  if (!api.query.welati?.electionVotes) {
    return false;
  }

  const vote = await api.query.welati.electionVotes(electionId, voterAddress);
  return vote.isSome;
}

/**
 * Get election results
 */
export async function getElectionResults(
  api: ApiPromise,
  electionId: number
): Promise<ElectionResult | null> {
  // Check if welati pallet exists
  if (!api.query.welati?.electionResults) {
    return null;
  }

  const result = await api.query.welati.electionResults(electionId);

  if (result.isNone) {
    return null;
  }

  const data = (result.unwrap() as any).toJSON() as any;

  return {
    electionId,
    winners: data.winners || [],
    totalVotes: data.totalVotes || 0,
    turnoutPercentage: data.turnoutPercentage || 0,
    finalizedAt: data.finalizedAt || 0,
    runoffRequired: data.runoffRequired || false,
  };
}

/**
 * Get active proposals
 */
export async function getActiveProposals(api: ApiPromise): Promise<CollectiveProposal[]> {
  // Check if welati pallet exists
  if (!api.query.welati?.nextProposalId) {
    return [];
  }

  const nextId = await api.query.welati.nextProposalId();
  const currentId = (nextId.toJSON() as number) || 0;

  const proposals: CollectiveProposal[] = [];

  // Query last 50 proposals
  for (let i = Math.max(0, currentId - 50); i < currentId; i++) {
    const proposal = await api.query.welati.activeProposals(i);

    if (proposal.isSome) {
      const data = (proposal.unwrap() as any).toJSON() as any;

      proposals.push({
        proposalId: i,
        proposer: data.proposer,
        title: data.title,
        description: data.description,
        proposedAt: data.proposedAt,
        votingStartsAt: data.votingStartsAt,
        expiresAt: data.expiresAt,
        decisionType: data.decisionType as CollectiveDecisionType,
        status: data.status as ProposalStatus,
        ayeVotes: data.ayeVotes || 0,
        nayVotes: data.nayVotes || 0,
        abstainVotes: data.abstainVotes || 0,
        threshold: data.threshold || 0,
        votesCast: data.votesCast || 0,
        priority: data.priority as ProposalPriority,
      });
    }
  }

  return proposals.filter(p => p.status === 'Active').reverse();
}

/**
 * Get proposal by ID
 */
export async function getProposalById(
  api: ApiPromise,
  proposalId: number
): Promise<CollectiveProposal | null> {
  // Check if welati pallet exists
  if (!api.query.welati?.activeProposals) {
    return null;
  }

  const proposal = await api.query.welati.activeProposals(proposalId);

  if (proposal.isNone) {
    return null;
  }

  const data = (proposal.unwrap() as any).toJSON() as any;

  return {
    proposalId,
    proposer: data.proposer,
    title: data.title,
    description: data.description,
    proposedAt: data.proposedAt,
    votingStartsAt: data.votingStartsAt,
    expiresAt: data.expiresAt,
    decisionType: data.decisionType as CollectiveDecisionType,
    status: data.status as ProposalStatus,
    ayeVotes: data.ayeVotes || 0,
    nayVotes: data.nayVotes || 0,
    abstainVotes: data.abstainVotes || 0,
    threshold: data.threshold || 0,
    votesCast: data.votesCast || 0,
    priority: data.priority as ProposalPriority,
  };
}

/**
 * Check if user has voted on a proposal
 */
export async function hasVotedOnProposal(
  api: ApiPromise,
  proposalId: number,
  voterAddress: string
): Promise<boolean> {
  // Check if welati pallet exists
  if (!api.query.welati?.collectiveVotes) {
    return false;
  }

  const vote = await api.query.welati.collectiveVotes(proposalId, voterAddress);
  return vote.isSome;
}

/**
 * Get user's vote on a proposal
 */
export async function getProposalVote(
  api: ApiPromise,
  proposalId: number,
  voterAddress: string
): Promise<VoteChoice | null> {
  // Check if welati pallet exists
  if (!api.query.welati?.collectiveVotes) {
    return null;
  }

  const vote = await api.query.welati.collectiveVotes(proposalId, voterAddress);

  if (vote.isNone) {
    return null;
  }

  const data = (vote.unwrap() as any).toJSON() as any;
  return data.vote as VoteChoice;
}

/**
 * Get pending appointments
 */
export async function getPendingAppointments(api: ApiPromise): Promise<AppointmentProcess[]> {
  // Check if welati pallet exists
  if (!api.query.welati?.nextAppointmentId) {
    return [];
  }

  const nextId = await api.query.welati.nextAppointmentId();
  const currentId = (nextId.toJSON() as number) || 0;

  const appointments: AppointmentProcess[] = [];

  for (let i = Math.max(0, currentId - 20); i < currentId; i++) {
    const appointment = await api.query.welati.appointmentProcesses(i);

    if (appointment.isSome) {
      const data = (appointment.unwrap() as any).toJSON() as any;

      if (data.status === 'Pending') {
        appointments.push({
          processId: i,
          nominee: data.nominee,
          role: data.role,
          nominator: data.nominator,
          justification: data.justification,
          status: data.status,
          createdAt: data.createdAt,
          deadline: data.deadline,
        });
      }
    }
  }

  return appointments;
}

/**
 * Get governance statistics
 */
export async function getGovernanceStats(api: ApiPromise): Promise<GovernanceMetrics> {
  // Check if welati pallet exists
  if (!api.query.welati?.governanceStats) {
    return {
      totalElectionsHeld: 0,
      activeElections: 0,
      parliamentSize: 0,
      diwanSize: 0,
      activeProposals: 0,
      totalProposalsSubmitted: 0,
      averageTurnout: 0,
    };
  }

  const stats = await api.query.welati.governanceStats();

  if (!stats || stats.isEmpty) {
    return {
      totalElectionsHeld: 0,
      activeElections: 0,
      parliamentSize: 0,
      diwanSize: 0,
      activeProposals: 0,
      totalProposalsSubmitted: 0,
      averageTurnout: 0,
    };
  }

  const data = stats.toJSON() as any;

  return {
    totalElectionsHeld: data.totalElectionsHeld || 0,
    activeElections: data.activeElections || 0,
    parliamentSize: data.parliamentSize || 0,
    diwanSize: data.diwanSize || 0,
    activeProposals: data.activeProposals || 0,
    totalProposalsSubmitted: data.totalProposalsSubmitted || 0,
    averageTurnout: data.averageTurnout || 0,
  };
}

/**
 * Get current block number
 */
export async function getCurrentBlock(api: ApiPromise): Promise<number> {
  const header = await api.rpc.chain.getHeader();
  return header.number.toNumber();
}

/**
 * Calculate remaining blocks until deadline
 */
export async function getRemainingBlocks(api: ApiPromise, deadlineBlock: number): Promise<number> {
  const currentBlock = await getCurrentBlock(api);
  return Math.max(0, deadlineBlock - currentBlock);
}

/**
 * Convert blocks to approximate time (6 seconds per block average)
 */
export function blocksToTime(blocks: number): {
  days: number;
  hours: number;
  minutes: number;
} {
  const seconds = blocks * 6;
  const days = Math.floor(seconds / 86400);
  const hours = Math.floor((seconds % 86400) / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);

  return { days, hours, minutes };
}

// ============================================================================
// HELPER FUNCTIONS
// ============================================================================

/**
 * Get election type label
 */
export function getElectionTypeLabel(type: ElectionType): { en: string; kmr: string } {
  const labels = {
    Presidential: { en: 'Presidential Election', kmr: 'Hilbijartina Serokî' },
    Parliamentary: { en: 'Parliamentary Election', kmr: 'Hilbijartina Parlamentoyê' },
    SpeakerElection: { en: 'Speaker Election', kmr: 'Hilbijartina Serokê Parlamentoyê' },
    ConstitutionalCourt: { en: 'Constitutional Court Election', kmr: 'Hilbijartina Dadgeha Destûrî' },
  };

  return labels[type] || { en: type, kmr: type };
}

/**
 * Get election status label
 */
export function getElectionStatusLabel(status: ElectionStatus): { en: string; kmr: string } {
  const labels = {
    CandidacyPeriod: { en: 'Candidate Registration Open', kmr: 'Qeydkirina Berendam Vekirî ye' },
    CampaignPeriod: { en: 'Campaign Period', kmr: 'Dema Kampanyayê' },
    VotingPeriod: { en: 'Voting Open', kmr: 'Dengdan Vekirî ye' },
    Completed: { en: 'Completed', kmr: 'Temam bû' },
  };

  return labels[status] || { en: status, kmr: status };
}

/**
 * Get minister role label
 */
export function getMinisterRoleLabel(role: MinisterRole): { en: string; kmr: string } {
  const labels = {
    WezireDarayiye: { en: 'Minister of Finance', kmr: 'Wezîrê Darayiyê' },
    WezireParez: { en: 'Minister of Defense', kmr: 'Wezîrê Parezê' },
    WezireDad: { en: 'Minister of Justice', kmr: 'Wezîrê Dadê' },
    WezireBelaw: { en: 'Minister of Education', kmr: 'Wezîrê Perwerdeyê' },
    WezireTend: { en: 'Minister of Health', kmr: 'Wezîrê Tendirustiyê' },
    WezireAva: { en: 'Minister of Water Resources', kmr: 'Wezîrê Avê' },
    WezireCand: { en: 'Minister of Culture', kmr: 'Wezîrê Çandî' },
  };

  return labels[role] || { en: role, kmr: role };
}

/**
 * Get proposal decision type threshold
 */
export function getDecisionTypeThreshold(type: CollectiveDecisionType, totalMembers: number): number {
  switch (type) {
    case 'ParliamentSimpleMajority':
      return Math.floor(totalMembers / 2) + 1; // > 50%
    case 'ParliamentSuperMajority':
    case 'ConstitutionalReview':
      return Math.ceil((totalMembers * 2) / 3); // > 66.67%
    case 'ParliamentAbsoluteMajority':
      return Math.ceil((totalMembers * 3) / 4); // > 75%
    case 'ConstitutionalUnanimous':
      return totalMembers; // 100%
    default:
      return Math.floor(totalMembers / 2) + 1;
  }
}
