'use client';

import './style.scss';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faGoogle } from '@fortawesome/free-brands-svg-icons';
import NavTabs from '../navTabs';
import { useConfigContext } from '@/contexts/configProvider';
import { fetchApi } from '@/lib/utils/client';
import { SnsLinkItem, SnsListResponse, SnsDisconnectResponse } from '@/types/sns';
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle
} from '@/components/ui/dialog';

const STATE_STORAGE_KEY = 'antooza-sns-google-state';
const GOOGLE_AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth';
const GOOGLE_SCOPES = 'openid email profile';

type ProviderMeta = {
	provider: 'Google' | 'Naver' | 'Kakao';
	label: string;
	description: string;
	enabled: boolean;
};

const PROVIDERS: ProviderMeta[] = [
	{ provider: 'Google', label: 'Google', description: 'Google 계정으로 개미투자에 빠르게 로그인할 수 있어요.', enabled: true },
	{ provider: 'Naver', label: 'Naver', description: '준비중입니다.', enabled: false },
	{ provider: 'Kakao', label: 'Kakao', description: '준비중입니다.', enabled: false }
];

function formatKoreanDateTime(iso: string|null): string
{
	if (!iso) {
		return '-';
	}
	const d = new Date(iso);
	if (Number.isNaN(d.getTime())) {
		return '-';
	}
	const yyyy = d.getFullYear();
	const mm = String(d.getMonth() + 1).padStart(2, '0');
	const dd = String(d.getDate()).padStart(2, '0');
	const hh = String(d.getHours()).padStart(2, '0');
	const mi = String(d.getMinutes()).padStart(2, '0');
	return `${yyyy}-${mm}-${dd} ${hh}:${mi}`;
}

export default function SnsLinkPage()
{
	const config = useConfigContext();
	const googleClientId = config?.external?.googleClientId ?? '';
	const [items, setItems] = useState<SnsLinkItem[]>([]);
	const [loading, setLoading] = useState(true);
	const [pendingProvider, setPendingProvider] = useState<string|null>(null);
	const [confirmTarget, setConfirmTarget] = useState<SnsLinkItem|null>(null);
	const [statusMessage, setStatusMessage] = useState<string|null>(null);

	const loadItems = useCallback(async () => {
		try {
			const res = await fetchApi<SnsListResponse>('/api/mypage/sns', { silent: true });
			if (res.data) {
				setItems(res.data.items);
			}
		} catch {
			// silent
		} finally {
			setLoading(false);
		}
	}, []);

	useEffect(() => {
		loadItems();
	}, [loadItems]);

	useEffect(() => {
		const url = new URL(window.location.href);
		const connected = url.searchParams.get('connected');
		const error = url.searchParams.get('error');
		if (connected) {
			setStatusMessage(`${connected.toUpperCase()} 계정 연동이 완료되었습니다.`);
			url.searchParams.delete('connected');
			window.history.replaceState({}, '', url.pathname + (url.search ? `${url.search}` : ''));
		}
		if (error) {
			setStatusMessage(`연동에 실패했습니다: ${error}`);
			url.searchParams.delete('error');
			window.history.replaceState({}, '', url.pathname + (url.search ? `${url.search}` : ''));
		}
	}, []);

	const itemMap = useMemo(() => {
		const map = new Map<string, SnsLinkItem>();
		items.forEach((item) => map.set(item.provider, item));
		return map;
	}, [items]);

	const handleConnectGoogle = useCallback(() => {
		if (!googleClientId) {
			setStatusMessage('Google OAuth 설정이 누락되어 있습니다. 관리자에게 문의해주세요.');
			return;
		}

		const state = (typeof crypto !== 'undefined' && 'randomUUID' in crypto)
			? crypto.randomUUID()
			: Math.random().toString(36).slice(2);

		try {
			window.sessionStorage.setItem(STATE_STORAGE_KEY, state);
		} catch {
			// silent
		}

		const redirectUri = `${window.location.origin}/auth/sns/google/callback`;
		const params = new URLSearchParams({
			response_type: 'code',
			access_type: 'offline',
			prompt: 'consent',
			state,
			redirect_uri: redirectUri,
			scope: GOOGLE_SCOPES,
			client_id: googleClientId,
			include_granted_scopes: 'true'
		});

		window.location.href = `${GOOGLE_AUTH_URL}?${params.toString()}`;
	}, [googleClientId]);

	const handleDisconnect = useCallback(async (item: SnsLinkItem) => {
		setPendingProvider(item.provider);
		try {
			const res = await fetchApi<SnsDisconnectResponse>(`/api/mypage/sns/${item.provider.toLowerCase()}`, {
				method: 'DELETE',
				silent: true
			});

			if (res.success) {
				if (res.data?.revoked) {
					setStatusMessage(`${item.provider} 연동이 해제되었습니다.`);
				} else {
					setStatusMessage(`${item.provider} 연동을 해제했지만 Google 측 권한 회수 호출이 실패했습니다. 안전하게 하려면 Google 계정 설정의 "보안 → 타사 앱 액세스" 에서도 개미투자 권한을 직접 제거해주세요.`);
				}
				await loadItems();
			} else {
				setStatusMessage(res.message || '연동 해제에 실패했습니다.');
			}
		} catch {
			setStatusMessage('연동 해제 중 오류가 발생했습니다.');
		} finally {
			setPendingProvider(null);
			setConfirmTarget(null);
		}
	}, [loadItems]);

	const handleToggle = useCallback((meta: ProviderMeta) => {
		if (!meta.enabled) {
			return;
		}
		const item = itemMap.get(meta.provider);

		if (item?.connected) {
			setConfirmTarget(item);
			return;
		}

		if (meta.provider === 'Google') {
			handleConnectGoogle();
		}
	}, [itemMap, handleConnectGoogle]);

	return (
		<>
		<NavTabs />

		<div id="sns-link">
			<h1>SNS 연결 관리</h1>
			<p className="sns-link__intro">
				외부 SNS 계정과 개미투자를 연결하면 빠른 로그인이 가능해집니다.
			</p>

			{statusMessage && (
				<div className="sns-link__status" role="status" aria-live="polite">
					<span>{statusMessage}</span>
					<button type="button" onClick={() => setStatusMessage(null)} aria-label="닫기">×</button>
				</div>
			)}

			<ul className="sns-link__list">
				{PROVIDERS.map((meta) => {
					const item = itemMap.get(meta.provider);
					const connected = item?.connected ?? false;
					const expired = item?.isExpired ?? false;
					const lastConnectedAt = item?.updatedAt ?? item?.connectedAt ?? null;
					const pending = pendingProvider === meta.provider;
					const disabled = !meta.enabled || pending || loading;

					return (
						<li key={meta.provider} className={`sns-link__item${connected ? ' sns-link__item--connected' : ''}${meta.enabled ? '' : ' sns-link__item--disabled'}`}>
							<div className={`sns-link__item-icon sns-link__item-icon--${meta.provider.toLowerCase()}`} aria-hidden="true">
								{meta.provider === 'Google' && <FontAwesomeIcon icon={faGoogle} />}
								{meta.provider === 'Naver' && <span className="sns-link__icon-text">N</span>}
								{meta.provider === 'Kakao' && <span className="sns-link__icon-text">K</span>}
							</div>

							<div className="sns-link__item-body">
								<div className="sns-link__item-title">
									{meta.label}
									{!meta.enabled && <span className="sns-link__badge sns-link__badge--soon">준비중</span>}
									{connected && expired && <span className="sns-link__badge sns-link__badge--warn">만료됨</span>}
								</div>
								<div className="sns-link__item-meta">
									{connected
										? <>마지막 연동: {formatKoreanDateTime(lastConnectedAt)}</>
										: <>{meta.description}</>
									}
								</div>
							</div>

							<button
								type="button"
								role="switch"
								aria-checked={connected}
								aria-label={connected ? `${meta.label} 연동 해제` : `${meta.label} 연동`}
								className={`sns-link__toggle${connected ? ' sns-link__toggle--on' : ''}${disabled ? ' sns-link__toggle--disabled' : ''}`}
								onClick={() => handleToggle(meta)}
								disabled={disabled}
								title={meta.enabled ? (connected ? '연동 해제' : '연동하기') : '준비중입니다'}
							>
								<span className="sns-link__toggle-knob" aria-hidden="true" />
								<span className="sns-link__toggle-label">{connected ? 'ON' : 'OFF'}</span>
							</button>
						</li>
					);
				})}
			</ul>
		</div>

		<Dialog
			open={confirmTarget !== null}
			onOpenChange={(next) => {
				if (!next) {
					setConfirmTarget(null);
				}
			}}
		>
			<DialogContent className="sns-link__dialog">
				<DialogHeader>
					<DialogTitle>{confirmTarget?.provider} 연동을 해제할까요?</DialogTitle>
					<DialogDescription>
						해제하면 개미투자에 저장된 OAuth 토큰이 삭제되고 Google 측 권한도 회수됩니다.
						언제든 다시 연동할 수 있습니다.
					</DialogDescription>
				</DialogHeader>
				<DialogFooter>
					<button
						type="button"
						className="sns-link__dialog-cancel"
						onClick={() => setConfirmTarget(null)}
						disabled={pendingProvider !== null}
					>
						취소
					</button>
					<button
						type="button"
						className="sns-link__dialog-confirm"
						onClick={() => confirmTarget && handleDisconnect(confirmTarget)}
						disabled={pendingProvider !== null}
					>
						{pendingProvider !== null ? '해제 중...' : '연동 해제'}
					</button>
				</DialogFooter>
			</DialogContent>
		</Dialog>
		</>
	);
}
