<template>
	<view class="page">
		<view class="header">
			<text class="title">监督人机制</text>
			<text class="subtitle">邀请朋友监督你的戒烟旅程，或者你来监督别人</text>
		</view>

		<view class="card">
			<view class="card-head">
				<text class="card-title">邀请监督人</text>
				<text class="card-meta">已绑定 {{ supervisorItems.length }}/3</text>
			</view>

			<view v-if="inviteToken" class="invite-box">
				<text class="invite-label">邀请口令</text>
				<text class="invite-token">{{ inviteToken }}</text>
				<text class="invite-hint">对方打开小程序后，进入“绑定监督”页面输入口令即可</text>

				<view class="invite-actions">
					<button class="btn btn-ghost" @tap="copyInviteToken">复制口令</button>
					<button class="btn" @tap="copyInvitePath">复制链接</button>
				</view>

				<text v-if="inviteExpireAt" class="invite-expire">过期时间：{{ formatDateTime(inviteExpireAt) }}</text>
			</view>

			<view v-else class="invite-empty">
				<text class="invite-empty-text">
					{{ supervisorItems.length >= 3 ? '监督人已满（最多 3 人），你可以先解除一个再邀请' : '生成一个邀请口令，发给你信得过的人' }}
				</text>
				<button class="btn" :disabled="inviteLoading || supervisorItems.length >= 3" @tap="generateInvite">
					{{ supervisorItems.length >= 3 ? '已达上限' : (inviteLoading ? '生成中...' : '生成邀请口令') }}
				</button>
			</view>
		</view>

		<view class="card">
			<view class="card-head">
				<text class="card-title">我监督的人</text>
				<text class="card-meta">{{ overviewItems.length }} 人</text>
			</view>

			<view v-if="overviewItems.length === 0" class="empty">
				<text class="empty-text">还没有绑定监督关系</text>
				<text class="empty-hint">收到口令后可去“绑定监督”页面完成绑定</text>
				<button class="btn btn-ghost" @tap="gotoBindPage">去绑定监督</button>
			</view>

			<view v-else class="list">
				<view v-for="item in overviewItems" :key="item.owner?.user_id" class="row">
					<image class="avatar" :src="item.owner?.avatar_url || defaultAvatar" mode="aspectFill"></image>
					<view class="row-main">
						<text class="name">{{ item.owner?.nickname || `用户 ${item.owner?.user_id}` }}</text>
						<view class="meta">
							<text class="pill">连续 {{ item.home?.summary?.current_streak_days || 0 }} 天</text>
							<text class="pill">HP {{ item.home?.summary?.hp_current ?? '--' }}</text>
							<text class="pill" :class="hpDeltaClass(item.home?.summary?.hp_change_today)">
								{{ hpDeltaText(item.home?.summary?.hp_change_today) }}
							</text>
						</view>
						<text class="status">今日：{{ statusText(item.home?.daily_status?.status) }}</text>
						<view class="row-actions">
							<button class="mini-btn" @tap.stop="confirmRevoke(item)">解除监督</button>
						</view>
					</view>
				</view>
			</view>
		</view>

		<view class="card">
			<view class="card-head">
				<text class="card-title">监督我的人</text>
				<text class="card-meta">{{ supervisorItems.length }} 人</text>
			</view>
			<view v-if="supervisorItems.length === 0" class="empty">
				<text class="empty-text">还没有人监督你</text>
				<text class="empty-hint">你可以先生成邀请口令发送给朋友</text>
			</view>
			<view v-else class="list">
				<view v-for="u in supervisorItems" :key="u.user_id" class="row">
					<image class="avatar" :src="u.avatar_url || defaultAvatar" mode="aspectFill"></image>
					<view class="row-main">
						<text class="name">{{ u.nickname || `用户 ${u.user_id}` }}</text>
						<text class="status">可查看你的戒烟概览</text>
					</view>
				</view>
			</view>
		</view>

		<view class="card">
			<view class="card-head">
				<text class="card-title">提醒设置</text>
				<text class="card-meta">默认关闭</text>
			</view>

			<view class="settings">
				<view class="setting-row">
					<text class="setting-label">启用提醒</text>
					<switch :checked="reminderEnabled" @change="onToggleReminder" />
				</view>

				<view class="setting-row">
					<text class="setting-label">提醒时间</text>
					<view class="setting-control">
						<button class="mini-btn mini-btn-neutral" :disabled="!reminderEnabled" @tap="pickNotifyTime">
							{{ reminderNotifyTime || '21:00' }}
						</button>
					</view>
				</view>

				<view class="setting-row">
					<text class="setting-label">每日上限</text>
					<view class="setting-control">
						<input
							class="num-input"
							type="number"
							:value="String(reminderMaxPerDay)"
							:disabled="!reminderEnabled"
							placeholder="1"
							@input="onMaxPerDayInput"
						/>
						<text class="setting-hint">每个监督人每天最多 N 次（建议 1）</text>
					</view>
				</view>

				<view class="setting-actions">
					<button class="btn btn-ghost" :disabled="savingSettings" @tap="reloadReminderSettings">重载</button>
					<button class="btn" :disabled="savingSettings" @tap="saveReminderSettings">
						{{ savingSettings ? '保存中...' : '保存设置' }}
					</button>
				</view>

				<text class="settings-note">提示：当前版本后端仅记录提醒日志（stub），尚未接入真实订阅消息发送。</text>
			</view>
		</view>

		<view class="card">
			<view class="card-head">
				<text class="card-title">提醒测试（监督人）</text>
				<text class="card-meta">仅写日志</text>
			</view>
			<view class="settings">
				<text class="settings-note">你作为监督人时，可手动触发一次提醒流程（用于联调频控与条件判断）。</text>
				<button class="btn" :disabled="runningReminders" @tap="runRemindersNow">
					{{ runningReminders ? '触发中...' : '手动触发提醒' }}
				</button>
				<text v-if="lastRunText" class="run-result">{{ lastRunText }}</text>
			</view>
		</view>

		<view class="footer">
			<button class="btn btn-ghost" :disabled="loading" @tap="refreshAll">刷新</button>
		</view>
	</view>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { useLogin } from '@/hooks/useLogin'
import { useUserStore } from '@/stores/user'
import {
	createSupervisorInvite,
	getSupervisorOverview,
	getSupervisorStatus,
	revokeSupervisorBinding,
	getSupervisorReminderSettings,
	updateSupervisorReminderSettings,
	runSupervisorReminders
} from '@/api/smoke'

const { waitForLogin } = useLogin()
const userStore = useUserStore()

const loading = ref(false)
const inviteLoading = ref(false)
const inviteToken = ref('')
const inviteExpireAt = ref('')

const overviewItems = ref([])
const supervisorItems = ref([])

const defaultAvatar = 'https://linghu-wmr.oss-cn-beijing.aliyuncs.com/smt/avatar.png'

const savingSettings = ref(false)
const reminderEnabled = ref(false)
const reminderNotifyTime = ref('21:00')
const reminderMaxPerDay = ref(1)

const runningReminders = ref(false)
const lastRunText = ref('')

function formatDateTime(value) {
	if (!value) return '--'
	const d = new Date(value)
	if (Number.isNaN(d.getTime())) return value
	const y = d.getFullYear()
	const m = String(d.getMonth() + 1).padStart(2, '0')
	const day = String(d.getDate()).padStart(2, '0')
	const hh = String(d.getHours()).padStart(2, '0')
	const mm = String(d.getMinutes()).padStart(2, '0')
	return `${y}-${m}-${day} ${hh}:${mm}`
}

function statusText(status) {
	if (status === 'checked_in') return '已打卡'
	if (status === 'relapsed') return '已复吸'
	if (status === 'pending') return '未打卡'
	if (status === 'missed') return '缺失'
	return status || '--'
}

function hpDeltaText(delta) {
	const n = Number(delta)
	if (Number.isNaN(n) || n === 0) return '今日 0'
	return n > 0 ? `今日 +${n}` : `今日 ${n}`
}

function hpDeltaClass(delta) {
	const n = Number(delta)
	if (Number.isNaN(n) || n === 0) return 'pill-muted'
	return n > 0 ? 'pill-up' : 'pill-down'
}

function copy(text) {
	if (!text) return
	uni.setClipboardData({
		data: text,
		success: () => uni.showToast({ title: '已复制', icon: 'success' })
	})
}

function invitePath() {
	if (!inviteToken.value) return ''
	return `/pages/supervisor/bind?token=${inviteToken.value}`
}

function copyInviteToken() {
	copy(inviteToken.value)
}

function copyInvitePath() {
	copy(invitePath())
}

function gotoBindPage() {
	uni.navigateTo({ url: '/pages/supervisor/bind' })
}

function confirmRevoke(item) {
	const ownerUID = item?.owner?.user_id
	if (!ownerUID) return
	uni.showModal({
		title: '解除监督',
		content: '解除后你将无法再查看对方的戒烟概览。确定要解除吗？',
		confirmText: '解除',
		confirmColor: '#b91c1c',
		success: async (res) => {
			if (!res.confirm) return
			await doRevoke(ownerUID)
		}
	})
}

async function doRevoke(ownerUID) {
	try {
		loading.value = true
		const myUID = Number(userStore.user?.id)
		if (!myUID) {
			uni.showToast({ title: '登录信息缺失', icon: 'none' })
			return
		}
		await revokeSupervisorBinding(ownerUID, myUID)
		uni.showToast({ title: '已解除', icon: 'success' })
		await refreshAll()
	} catch (e) {
		console.error('revoke error:', e)
		uni.showToast({ title: '解除失败', icon: 'none' })
	} finally {
		loading.value = false
	}
}

async function generateInvite() {
	if (inviteLoading.value) return
	inviteLoading.value = true
	try {
		const res = await createSupervisorInvite(7)
		inviteToken.value = res.data?.token || ''
		inviteExpireAt.value = res.data?.expire_at || ''
		if (!inviteToken.value) {
			uni.showToast({ title: '生成失败', icon: 'none' })
		}
	} catch (e) {
		console.error('generateInvite error:', e)
		uni.showToast({ title: '生成失败', icon: 'none' })
	} finally {
		inviteLoading.value = false
	}
}

async function refreshAll() {
	if (loading.value) return
	loading.value = true
	try {
		const [overview, status, reminder] = await Promise.all([
			getSupervisorOverview(),
			getSupervisorStatus(),
			getSupervisorReminderSettings()
		])
		overviewItems.value = overview.data?.items || []
		supervisorItems.value = status.data?.items || []
		applyReminderSettings(reminder.data)
	} catch (e) {
		console.error('refreshAll error:', e)
		uni.showToast({ title: '刷新失败', icon: 'none' })
	} finally {
		loading.value = false
	}
}

function applyReminderSettings(data) {
	reminderEnabled.value = !!data?.enabled
	reminderNotifyTime.value = data?.notify_time || '21:00'
	const maxN = Number(data?.max_per_day)
	reminderMaxPerDay.value = Number.isNaN(maxN) ? 1 : Math.min(Math.max(maxN, 0), 10)
}

async function reloadReminderSettings() {
	try {
		const res = await getSupervisorReminderSettings()
		applyReminderSettings(res.data)
		uni.showToast({ title: '已重载', icon: 'success' })
	} catch (e) {
		console.error('reloadReminderSettings error:', e)
		uni.showToast({ title: '重载失败', icon: 'none' })
	}
}

function onToggleReminder(e) {
	reminderEnabled.value = !!e?.detail?.value
}

function pickNotifyTime() {
	if (!reminderEnabled.value) return
	uni.showModal({
		title: '设置提醒时间',
		content: '当前版本请手动输入 HH:MM（例如 21:00）。',
		editable: true,
		placeholderText: reminderNotifyTime.value || '21:00',
		success: (res) => {
			if (!res.confirm) return
			const v = String(res.content || '').trim()
			if (!/^\d{2}:\d{2}$/.test(v)) {
				uni.showToast({ title: '格式应为 HH:MM', icon: 'none' })
				return
			}
			reminderNotifyTime.value = v
		}
	})
}

function onMaxPerDayInput(e) {
	const v = Number(e?.detail?.value)
	if (Number.isNaN(v)) {
		reminderMaxPerDay.value = 1
		return
	}
	reminderMaxPerDay.value = Math.min(Math.max(Math.floor(v), 0), 10)
}

async function saveReminderSettings() {
	if (savingSettings.value) return
	savingSettings.value = true
	try {
		const payload = {
			enabled: reminderEnabled.value,
			notify_time: reminderNotifyTime.value,
			max_per_day: reminderMaxPerDay.value
		}
		const res = await updateSupervisorReminderSettings(payload)
		applyReminderSettings(res.data)
		uni.showToast({ title: '已保存', icon: 'success' })
	} catch (e) {
		console.error('saveReminderSettings error:', e)
		uni.showToast({ title: '保存失败', icon: 'none' })
	} finally {
		savingSettings.value = false
	}
}

async function runRemindersNow() {
	if (runningReminders.value) return
	runningReminders.value = true
	lastRunText.value = ''
	try {
		const res = await runSupervisorReminders()
		const created = res.data?.created ?? 0
		const skipped = res.data?.skipped ?? 0
		lastRunText.value = `本次触发：写入 ${created} 条，跳过 ${skipped} 条`
		uni.showToast({ title: '已触发', icon: 'success' })
	} catch (e) {
		console.error('runRemindersNow error:', e)
		uni.showToast({ title: '触发失败', icon: 'none' })
	} finally {
		runningReminders.value = false
	}
}

onMounted(() => {})

onShow(async () => {
	await waitForLogin()
	await refreshAll()
})
</script>

<style scoped>
.page {
	min-height: 100vh;
	padding: 28rpx 28rpx 40rpx;
	box-sizing: border-box;
	background: linear-gradient(180deg, #eef7f3 0%, #f7faf8 40%, #fbfdff 100%);
}

.header {
	padding: 8rpx 6rpx 18rpx;
}

.title {
	display: block;
	font-size: 40rpx;
	font-weight: 800;
	color: #0f172a;
	letter-spacing: 0.5rpx;
}

.subtitle {
	display: block;
	margin-top: 10rpx;
	font-size: 24rpx;
	line-height: 1.6;
	color: #64748b;
}

.card {
	margin-top: 18rpx;
	background: rgba(255, 255, 255, 0.92);
	border-radius: 26rpx;
	border: 1rpx solid rgba(15, 23, 42, 0.06);
	padding: 22rpx 22rpx;
	box-shadow: 0 10rpx 26rpx rgba(15, 23, 42, 0.05);
}

.card-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16rpx;
}

.card-title {
	font-size: 28rpx;
	font-weight: 800;
	color: #0f172a;
}

.card-meta {
	font-size: 22rpx;
	color: #94a3b8;
}

.invite-box {
	margin-top: 18rpx;
}

.invite-label {
	display: block;
	font-size: 22rpx;
	color: #64748b;
}

.invite-token {
	display: block;
	margin-top: 10rpx;
	font-size: 36rpx;
	font-weight: 900;
	letter-spacing: 2rpx;
	color: #0f766e;
	font-family: 'DIN Alternate', -apple-system, sans-serif;
}

.invite-hint {
	display: block;
	margin-top: 10rpx;
	font-size: 22rpx;
	line-height: 1.6;
	color: #475569;
}

.invite-actions {
	display: flex;
	gap: 14rpx;
	margin-top: 16rpx;
}

.invite-expire {
	display: block;
	margin-top: 14rpx;
	font-size: 22rpx;
	color: #94a3b8;
}

.invite-empty {
	margin-top: 18rpx;
	display: flex;
	flex-direction: column;
	gap: 16rpx;
}

.invite-empty-text {
	font-size: 24rpx;
	line-height: 1.6;
	color: #475569;
}

.empty {
	margin-top: 18rpx;
	padding: 16rpx 6rpx 6rpx;
}

.empty-text {
	display: block;
	font-size: 24rpx;
	font-weight: 700;
	color: #0f172a;
}

.empty-hint {
	display: block;
	margin-top: 10rpx;
	font-size: 22rpx;
	line-height: 1.6;
	color: #64748b;
}

.list {
	margin-top: 18rpx;
	display: flex;
	flex-direction: column;
	gap: 14rpx;
}

.row {
	display: flex;
	gap: 16rpx;
	align-items: flex-start;
	padding: 16rpx;
	border-radius: 20rpx;
	background: rgba(241, 245, 249, 0.6);
	border: 1rpx solid rgba(15, 23, 42, 0.04);
}

.avatar {
	width: 74rpx;
	height: 74rpx;
	border-radius: 50%;
	background: #e2e8f0;
	flex-shrink: 0;
}

.row-main {
	flex: 1;
	min-width: 0;
}

.name {
	display: block;
	font-size: 28rpx;
	font-weight: 800;
	color: #0f172a;
}

.meta {
	margin-top: 10rpx;
	display: flex;
	gap: 10rpx;
	flex-wrap: wrap;
}

.pill {
	padding: 8rpx 12rpx;
	border-radius: 999rpx;
	background: #ffffff;
	border: 1rpx solid rgba(15, 23, 42, 0.06);
	font-size: 20rpx;
	color: #334155;
}

.pill-muted {
	color: #64748b;
}

.pill-up {
	color: #0f766e;
	background: rgba(204, 251, 241, 0.6);
}

.pill-down {
	color: #b91c1c;
	background: rgba(254, 226, 226, 0.8);
}

.status {
	display: block;
	margin-top: 10rpx;
	font-size: 22rpx;
	color: #64748b;
}

.row-actions {
	margin-top: 12rpx;
	display: flex;
	justify-content: flex-end;
}

.mini-btn {
	height: 56rpx;
	line-height: 56rpx;
	padding: 0 18rpx;
	border-radius: 14rpx;
	background: #ffffff;
	border: 1rpx solid rgba(185, 28, 28, 0.28);
	color: #b91c1c;
	font-size: 22rpx;
	font-weight: 700;
}

.footer {
	margin-top: 20rpx;
	padding-bottom: 20rpx;
	display: flex;
	justify-content: center;
}

.btn {
	height: 76rpx;
	line-height: 76rpx;
	padding: 0 22rpx;
	border-radius: 18rpx;
	background: linear-gradient(180deg, #1aa37a 0%, #0f766e 100%);
	color: #ffffff;
	font-size: 26rpx;
	font-weight: 700;
}

.btn[disabled] {
	opacity: 0.6;
}

.btn-ghost {
	background: #ffffff;
	color: #0f766e;
	border: 1rpx solid rgba(15, 118, 110, 0.25);
}

.mini-btn-neutral {
	border-color: rgba(15, 23, 42, 0.12);
	color: #334155;
}

.settings {
	margin-top: 18rpx;
	display: flex;
	flex-direction: column;
	gap: 16rpx;
}

.setting-row {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 18rpx;
	padding: 14rpx 12rpx;
	border-radius: 18rpx;
	background: rgba(241, 245, 249, 0.45);
	border: 1rpx solid rgba(15, 23, 42, 0.04);
}

.setting-label {
	font-size: 24rpx;
	font-weight: 800;
	color: #0f172a;
	padding-top: 6rpx;
}

.setting-control {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 10rpx;
}

.num-input {
	width: 200rpx;
	height: 64rpx;
	padding: 0 14rpx;
	border-radius: 14rpx;
	background: rgba(255, 255, 255, 0.92);
	border: 1rpx solid rgba(15, 23, 42, 0.08);
	font-size: 26rpx;
	text-align: right;
}

.setting-hint {
	font-size: 20rpx;
	line-height: 1.5;
	color: #64748b;
	text-align: right;
}

.setting-actions {
	display: flex;
	gap: 14rpx;
}

.settings-note {
	font-size: 22rpx;
	line-height: 1.6;
	color: #64748b;
}

.run-result {
	font-size: 22rpx;
	color: #0f766e;
	font-weight: 700;
}
</style>
