<template>
    <div v-if="ringingSessions.length > 0" class="ringing-call-float" :style="floatStyle">
        <div v-for="session in ringingSessions" :key="session.id" class="ringing-card"
            @mousedown.stop="handleDragStart">
            <div class="ringing-card-info">
                <div class="ringing-card-title">
                    {{ session.name }}<span class="ringing-card-count">({{ session.displayTimeout }})</span>
                </div>
                <div class="ringing-card-source">{{ session.source || '' }}</div>
            </div>
            <button class="ringing-card-accept" type="button" @mousedown.stop @click.stop="handleAccept(session.id)">
                <span class="ringing-card-icon">
                    <img class="ringing-card-icon-default" :src="notHoverCallInIcon" alt="接听" draggable="false" />
                    <img class="ringing-card-icon-hover" :src="hoverCallInIcon" alt="接听" draggable="false" />
                </span>
            </button>
        </div>
    </div>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import AIDeskCoreInstance, {
    SESSION_TYPE,
    StoreName,
    type ISessionModel,
} from '@tencentcloud/ai-desk-core';
import notHoverCallInIcon from './notHoverCallIn.svg';
import hoverCallInIcon from './HoverCallIn.svg';
import { getSessionShowSource } from '../../../../utils';

interface RingingSession {
    id: string;
    name: string;
    source: string;
    timeout: number;
    startAt: number;
    displayTimeout: number;
}

const STORAGE_KEY = 'ai-desk-ringing-float-position';
const CARD_WIDTH = 360;
const CARD_HEIGHT = 72;
const CARD_GAP = 12;
const EDGE_PADDING = 12;
const RINGING_TIMER_INTERVAL = 200;

const rawIMList = ref<ISessionModel<SESSION_TYPE.IM>[]>([]);
const now = ref(Date.now());

const position = ref<{ x: number; y: number }>(loadPosition());

let ringingTimer: number | undefined;
let dragState: {
    startX: number;
    startY: number;
    originX: number;
    originY: number;
    moved: boolean;
} | null = null;

function loadPosition(): { x: number; y: number } {
    try {
        const raw = window.localStorage.getItem(STORAGE_KEY);
        if (raw) {
            const parsed = JSON.parse(raw);
            if (typeof parsed?.x === 'number' && typeof parsed?.y === 'number') {
                return { x: parsed.x, y: parsed.y };
            }
        }
    } catch (e) {
        // ignore
    }
    // 默认位置：靠右上
    const defaultX = Math.max(EDGE_PADDING, window.innerWidth - CARD_WIDTH - EDGE_PADDING - 24);
    const defaultY = 80;
    return { x: defaultX, y: defaultY };
}

function savePosition() {
    try {
        window.localStorage.setItem(STORAGE_KEY, JSON.stringify(position.value));
    } catch (e) {
        // ignore
    }
}

function clampPosition(x: number, y: number, totalHeight: number) {
    const maxX = Math.max(EDGE_PADDING, window.innerWidth - CARD_WIDTH - EDGE_PADDING);
    const maxY = Math.max(EDGE_PADDING, window.innerHeight - totalHeight - EDGE_PADDING);
    return {
        x: Math.min(Math.max(x, EDGE_PADDING), maxX),
        y: Math.min(Math.max(y, EDGE_PADDING), maxY),
    };
}

const ringingSessions = computed<RingingSession[]>(() => {
    return rawIMList.value
        .filter((item) => item.sessionData.sessionState === 'ringing')
        .map((item) => {
            const timeout = Number(item.sessionData.timeout ?? 0);
            const safeTimeout = Number.isFinite(timeout) ? Math.max(timeout, 0) : 0;
            const startAt = Number(item.sessionData.timestamp || Date.now());
            const elapsed = Math.max((now.value - startAt) / 1000, 0);
            const remaining = Math.max(safeTimeout - elapsed, 0);
            return {
                id: item.sessionId,
                name: item.sessionData.nickname || item.sessionData.userId || '',
                source: getSessionShowSource(item.sessionData.peerSource, item.sessionData.clientData) || '',
                timeout: safeTimeout,
                startAt,
                displayTimeout: Math.max(0, Math.ceil(remaining)),
            };
        });
});

const totalHeight = computed(() => {
    const count = ringingSessions.value.length;
    if (count <= 0) return 0;
    return count * CARD_HEIGHT + (count - 1) * CARD_GAP;
});

const floatStyle = computed(() => {
    const clamped = clampPosition(position.value.x, position.value.y, totalHeight.value);
    return {
        left: `${clamped.x}px`,
        top: `${clamped.y}px`,
        width: `${CARD_WIDTH}px`,
    };
});

const onIMSessionListUpdated = (list: ISessionModel<SESSION_TYPE.IM>[]) => {
    rawIMList.value = list ?? [];
};

const startRingingTimer = () => {
    stopRingingTimer();
    ringingTimer = window.setInterval(() => {
        now.value = Date.now();
    }, RINGING_TIMER_INTERVAL);
};

const stopRingingTimer = () => {
    if (ringingTimer !== undefined) {
        window.clearInterval(ringingTimer);
        ringingTimer = undefined;
    }
};

watch(
    () => ringingSessions.value.length,
    (count) => {
        if (count > 0) {
            startRingingTimer();
        } else {
            stopRingingTimer();
        }
    },
    { immediate: true },
);

const handleDragStart = (event: MouseEvent) => {
    dragState = {
        startX: event.clientX,
        startY: event.clientY,
        originX: position.value.x,
        originY: position.value.y,
        moved: false,
    };
    window.addEventListener('mousemove', handleDragMove);
    window.addEventListener('mouseup', handleDragEnd);
};

const handleDragMove = (event: MouseEvent) => {
    if (!dragState) return;
    const dx = event.clientX - dragState.startX;
    const dy = event.clientY - dragState.startY;
    if (!dragState.moved && Math.abs(dx) + Math.abs(dy) < 3) {
        return;
    }
    dragState.moved = true;
    const next = clampPosition(
        dragState.originX + dx,
        dragState.originY + dy,
        totalHeight.value,
    );
    position.value = next;
};

const handleDragEnd = () => {
    window.removeEventListener('mousemove', handleDragMove);
    window.removeEventListener('mouseup', handleDragEnd);
    if (dragState?.moved) {
        savePosition();
    }
    dragState = null;
};

const handleAccept = (sessionId: string) => {
    AIDeskCoreInstance.sessionService.acceptSession(sessionId);
};

const handleWindowResize = () => {
    const next = clampPosition(position.value.x, position.value.y, totalHeight.value);
    position.value = next;
    savePosition();
};

onMounted(() => {
    AIDeskCoreInstance.coreStore.watch(StoreName.SESSION, {
        IMSessionList: onIMSessionListUpdated,
    });
    window.addEventListener('resize', handleWindowResize);
});

onUnmounted(() => {
    AIDeskCoreInstance.coreStore.unwatch(StoreName.SESSION, {
        IMSessionList: onIMSessionListUpdated,
    });
    window.removeEventListener('resize', handleWindowResize);
    window.removeEventListener('mousemove', handleDragMove);
    window.removeEventListener('mouseup', handleDragEnd);
    stopRingingTimer();
});
</script>

<style scoped>
.ringing-call-float {
    position: fixed;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    gap: 12px;
    user-select: none;
}

.ringing-card {
    height: 72px;
    box-sizing: border-box;
    padding: 12px 12px 12px 20px;
    background: #0F1E3A;
    color: #fff;
    border-radius: 12px;
    display: flex;
    align-items: center;
    gap: 12px;
    box-shadow: 0 8px 24px rgba(15, 30, 58, 0.24);
    cursor: grab;
}

.ringing-card:active {
    cursor: grabbing;
}

.ringing-card-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ringing-card-title {
    font-size: 16px;
    font-weight: 600;
    line-height: 22px;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ringing-card-count {
    margin-left: 4px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.9);
}

.ringing-card-source {
    font-size: 12px;
    line-height: 18px;
    color: rgba(255, 255, 255, 0.7);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ringing-card-accept {
    position: relative;
    flex-shrink: 0;
    width: 34px;
    height: 34px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    outline: none;
}

.ringing-card-icon {
    position: relative;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    transition: background 0.2s ease;
}

.ringing-card-icon-default,
.ringing-card-icon-hover {
    position: absolute;
    width: 20px;
    height: 20px;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

.ringing-card-icon-hover {
    opacity: 0;
}

.ringing-card-accept:hover .ringing-card-icon {
    background: #12B282;
}

.ringing-card-accept:hover .ringing-card-icon-default {
    opacity: 0;
}

.ringing-card-accept:hover .ringing-card-icon-hover {
    opacity: 1;
}
</style>
