import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { useConnectionStore } from './connection';
import { TICKET_TYPES, type TicketType } from '@gala/shared/constants';
import { showToast } from 'vant';
import type { VoteStamp } from '@gala/shared/types';

// Ticket display info
export const TICKET_INFO: Record<TicketType, { name: string; icon: string }> = {
  creative: { name: '最佳创意', icon: 'creative' },
  visual: { name: '最佳视觉', icon: 'visual' },
  atmosphere: { name: '最佳氛围', icon: 'atmosphere' },
  performance: { name: '最佳表演', icon: 'performance' },
  teamwork: { name: '最佳团队', icon: 'teamwork' },
  popularity: { name: '最受欢迎', icon: 'popularity' },
  potential: { name: '最具潜力', icon: 'potential' },
};

interface PendingVote {
  ticketType: TicketType;
  programId: string;
  timestamp: number;
}

interface VotingProgram {
  id: string;
  name: string;
  teamName: string;
  order: number;
  status: 'pending' | 'voting' | 'completed';
  votes: number;
}

export const useVotingStore = defineStore('voting', () => {
  const connectionStore = useConnectionStore();

  // State: ticketType -> programId (null if unused)
  const tickets = ref<Record<TicketType, string | null>>({
    creative: null,
    visual: null,
    atmosphere: null,
    performance: null,
    teamwork: null,
    popularity: null,
    potential: null,
  });

  // Server-synced voting state
  const votingOpen = ref(false);
  const votingPaused = ref(false);
  const programs = ref<VotingProgram[]>([]);
  const currentProgramId = ref<string | null>(null);
  const allowLateCatch = ref(true);

  // Currently selected stamp in dock
  const selectedStamp = ref<TicketType | null>(null);

  // Pending votes (optimistic updates waiting for server confirmation)
  const pendingVotes = ref<Map<string, PendingVote>>(new Map());

  // Animation state for cards
  const stampingCard = ref<string | null>(null);

  // Computed
  const usedTickets = computed(() => {
    return TICKET_TYPES.filter((t) => tickets.value[t] !== null);
  });

  const availableTickets = computed(() => {
    return TICKET_TYPES.filter((t) => tickets.value[t] === null);
  });

  const isStampSelected = computed(() => selectedStamp.value !== null);

  // Check if a program has received any stamp from this user
  function getProgramStamp(programId: string): TicketType | null {
    for (const ticketType of TICKET_TYPES) {
      if (tickets.value[ticketType] === programId) {
        return ticketType;
      }
    }
    return null;
  }

  // Select a stamp from the dock
  function selectStamp(ticketType: TicketType) {
    if (tickets.value[ticketType] !== null) {
      showToast({ message: '该印章已使用', position: 'bottom' });
      return;
    }
    selectedStamp.value = ticketType;
  }

  // Deselect stamp
  function deselectStamp() {
    selectedStamp.value = null;
  }

  // Trigger haptic feedback
  function triggerHaptic() {
    if ('vibrate' in navigator) {
      navigator.vibrate(50);
    }
  }

  // Cast vote with optimistic update
  async function castVote(programId: string): Promise<boolean> {
    const ticketType = selectedStamp.value;
    if (!ticketType) {
      showToast({ message: '请先选择一个印章', position: 'bottom' });
      return false;
    }

    // Check if already voted for this program
    const existingStamp = getProgramStamp(programId);
    if (existingStamp) {
      showToast({ message: '已为该节目投过票', position: 'bottom' });
      return false;
    }

    // Optimistic update
    const previousValue = tickets.value[ticketType];
    tickets.value[ticketType] = programId;
    stampingCard.value = programId;

    // Trigger haptic
    triggerHaptic();

    // Create pending vote record
    const voteKey = `${ticketType}:${programId}`;
    pendingVotes.value.set(voteKey, {
      ticketType,
      programId,
      timestamp: Date.now(),
    });

    // Clear selection
    selectedStamp.value = null;

    // Call backend
    try {
      const socket = connectionStore.getSocket();
      if (!socket) {
        throw new Error('Not connected');
      }

      const localId = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;

      const result = await new Promise<{ success: boolean; error?: string; message?: string }>((resolve) => {
        const timeoutId = setTimeout(() => {
          resolve({ success: false, error: 'TIMEOUT', message: '网络超时，请重试' });
        }, 10000);

        socket.emit('vote:submit' as any, {
          candidateId: programId,
          category: ticketType,
          clientTimestamp: Date.now(),
          localId,
        }, (response: any) => {
          clearTimeout(timeoutId);
          resolve(response);
        });
      });

      if (!result.success) {
        // Use server message if available
        const errorMessage = result.message || '投票失败，请重试';
        throw new Error(errorMessage);
      }

      // Success - remove from pending
      pendingVotes.value.delete(voteKey);
      return true;

    } catch (error) {
      // Revert optimistic update
      tickets.value[ticketType] = previousValue;
      pendingVotes.value.delete(voteKey);

      const errorMessage = error instanceof Error ? error.message : '投票失败，请重试';
      showToast({
        message: errorMessage,
        position: 'bottom',
        type: 'fail',
      });
      return false;

    } finally {
      // Clear animation state after delay
      setTimeout(() => {
        stampingCard.value = null;
      }, 600);
    }
  }

  // Revoke a vote
  async function revokeVote(ticketType: TicketType): Promise<boolean> {
    const programId = tickets.value[ticketType];
    if (!programId) return false;

    // Optimistic update
    tickets.value[ticketType] = null;

    try {
      const socket = connectionStore.getSocket();
      if (!socket) throw new Error('Not connected');

      const result = await new Promise<{ success: boolean }>((resolve) => {
        socket.emit('vote:revoke' as any, { ticketType }, (response: any) => {
          resolve(response);
        });
        setTimeout(() => resolve({ success: false }), 10000);
      });

      if (!result.success) throw new Error('Revoke failed');
      return true;

    } catch {
      // Revert
      tickets.value[ticketType] = programId;
      showToast({ message: '撤销失败', position: 'bottom', type: 'fail' });
      return false;
    }
  }

  // Sync state from server
  function syncFromServer(serverTickets: Record<TicketType, string | null>) {
    tickets.value = { ...serverTickets };
  }

  // Sync voting state from AdminState
  function syncVotingState(state: {
    votingOpen?: boolean;
    votingPaused?: boolean;
    programs?: VotingProgram[];
    currentProgramId?: string | null;
    allowLateCatch?: boolean;
  }) {
    if (state.votingOpen !== undefined) votingOpen.value = state.votingOpen;
    if (state.votingPaused !== undefined) votingPaused.value = state.votingPaused;
    if (state.programs !== undefined) programs.value = state.programs;
    if (state.currentProgramId !== undefined) currentProgramId.value = state.currentProgramId;
    if (state.allowLateCatch !== undefined) allowLateCatch.value = state.allowLateCatch;
  }

  // Check if voting is allowed for a specific program
  // In unified voting mode, all programs can be voted when voting is open
  function canVoteForProgram(programId: string): { allowed: boolean; reason?: string } {
    // Check if voting is open
    if (!votingOpen.value) {
      return { allowed: false, reason: '投票尚未开始' };
    }
    if (votingPaused.value) {
      return { allowed: false, reason: '投票已暂停' };
    }

    // In unified voting mode, all programs are votable when voting is open
    return { allowed: true };
  }

  // Handle real-time vote updates
  function handleVoteUpdate(data: { candidateId: string; newCount: number; totalVotes: number }) {
    const program = programs.value.find(p => p.id === data.candidateId);
    if (program) {
      program.votes = data.newCount;
    }
    // Update global total votes if provided
    if (data.totalVotes !== undefined) {
      // We don't have a totalVotes ref in the store yet, but we could add it or just ignore
    }
  }

  // Get current voting program
  const currentProgram = computed(() => {
    if (!currentProgramId.value) return null;
    return programs.value.find(p => p.id === currentProgramId.value) || null;
  });

  // Get votable programs (voting or completed with late catch)
  const votablePrograms = computed(() => {
    return programs.value.filter(p => {
      if (p.status === 'voting') return true;
      if (p.status === 'completed' && allowLateCatch.value) return true;
      return false;
    });
  });

  return {
    tickets,
    selectedStamp,
    pendingVotes,
    stampingCard,
    usedTickets,
    availableTickets,
    isStampSelected,
    getProgramStamp,
    selectStamp,
    deselectStamp,
    castVote,
    revokeVote,
    syncFromServer,
    // New exports
    votingOpen,
    votingPaused,
    programs,
    currentProgramId,
    allowLateCatch,
    currentProgram,
    votablePrograms,
    syncVotingState,
    canVoteForProgram,
    handleVoteUpdate,
  };
});

