import discord
from discord.ext import commands
import os
import csv
from datetime import datetime
import unicodedata

# 檔案資料夾路徑設置
data_folder = "data/reminder_files"
data_file = "data/reminder_data.csv"
os.makedirs(data_folder, exist_ok=True)
if not os.path.exists(data_file):
    with open(data_file, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerow(["reminder_userID_time", "Title", "Content", "First Reminder Time", "Repeat Count", "Repeat Interval", "Files"])

# 定義提醒事項表單
class ReminderForm(discord.ui.Modal, title="提醒事項填寫表單"):
    reminder_title = discord.ui.TextInput(label="提醒事項標題", max_length=50, required=True)
    reminder_content = discord.ui.TextInput(
        label="提醒事項內容", 
        style=discord.TextStyle.paragraph, 
        max_length=200, 
        required=True
    )
    first_reminder = discord.ui.TextInput(
        label="第一次發送提醒的時間 (格式：YYYY-MM-DD HH:MM)", 
        required=True
    )
    repeat_count = discord.ui.TextInput(label="重複提醒的次數 (可留空)", required=False)
    repeat_interval = discord.ui.TextInput(label="重複提醒的間隔時間 (小時，可留空)", required=False)

    async def on_submit(self, interaction: discord.Interaction):
        # 檢查時間格式
        try:
            datetime.strptime(self.first_reminder.value, "%Y-%m-%d %H:%M")
        except ValueError:
            await interaction.response.send_message("時間格式不正確，請重新填寫。", ephemeral=True)
            return

        reminder_data = {
            "ID": f"{interaction.user.id}_{int(datetime.now().timestamp())}",
            "Title": self.reminder_title.value,
            "Content": self.reminder_content.value,
            "First Reminder Time": self.first_reminder.value,
            "Repeat Count": self.repeat_count.value or "0",
            "Repeat Interval": self.repeat_interval.value or "0",
            "Files": ""
        }

        await interaction.response.send_message(
            f"填寫內容如下：\n**標題**：{self.reminder_title.value}\n"
            f"**內容**：{self.reminder_content.value}\n"
            f"**第一次提醒時間**：{self.first_reminder.value}\n"
            f"**重複次數**：{reminder_data['Repeat Count']}\n"
            f"**間隔時間**：{reminder_data['Repeat Interval']} 小時\n"
            f"請確認是否正確。",
            ephemeral=True,
            view=ConfirmationView(reminder_data)
        )

class ButtonDisabler:
    @staticmethod
    def disable_and_stop(view, button):
        """禁用按鈕並停止視圖"""
        button.disabled = True
        view.stop()

# 確認與重新填寫
class ConfirmationView(discord.ui.View):
    def __init__(self, reminder_data):
        super().__init__()
        self.reminder_data = reminder_data

    @discord.ui.button(label="填寫正確", style=discord.ButtonStyle.success)
    async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button) # 使用 ButtonDisabler 禁用按鈕並停止視圖
        await interaction.response.send_message("您是否需要上傳相關檔案？", ephemeral=True, view=FileUploadView(self.reminder_data))

    @discord.ui.button(label="填寫不正確", style=discord.ButtonStyle.danger)
    async def incorrect(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        await interaction.response.send_message("是否需要重新填寫？", ephemeral=True, view=ReentryView(self.reminder_data))

class ReentryView(discord.ui.View):
    def __init__(self, reminder_data):
        super().__init__()
        self.reminder_data = reminder_data

    @discord.ui.button(label="是，並且刪除剛剛所填寫的資料", style=discord.ButtonStyle.danger)
    async def reenter(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        await interaction.response.send_modal(ReminderForm())

    @discord.ui.button(label="否，並且刪除剛剛所填寫的資料", style=discord.ButtonStyle.secondary)
    async def delete(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        await interaction.response.send_message("剛剛填寫的資料已刪除。", ephemeral=True)

# 檔案上傳
class FileUploadView(discord.ui.View):
    def __init__(self, reminder_data, files = None):
        super().__init__()
        self.reminder_data = reminder_data
        self.files = files if files else []

    @discord.ui.button(label="是", style=discord.ButtonStyle.success)
    async def upload(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)

        cancel_view = CancelUploadView(self.reminder_data, self.files)
        await interaction.response.send_message("請上傳檔案。", ephemeral=True, view=cancel_view)

        def check(m):
            return m.author == interaction.user and m.attachments

        try:
            message = await interaction.client.wait_for("message", check=check, timeout=300) # timeout是秒數
            reminder_folder = os.path.join(data_folder, self.reminder_data["ID"])
            os.makedirs(reminder_folder, exist_ok=True)
            success_files = []
            fail_files = []

            for attachment in message.attachments:
                # 確保檔案名稱以 UTF-8 編碼處理 
                #file_name = attachment.filename #.encode('utf-8').decode('utf-8')
                file_name = unicodedata.normalize('NFC', attachment.filename)
                file_path = os.path.join(reminder_folder, file_name)
                print(f"Discord 附件檔案名稱：{repr(attachment.filename)}")
                print(f"處理後檔案名稱：{file_name}")
                print(f"儲存路徑：{file_path}")

                try:
                    await attachment.save(os.path.normpath(file_path))
                    if (attachment.filename not in success_files) and (attachment.filename not in self.files):
                        success_files.append(attachment.filename)
                        self.files.append(attachment.filename)
                except Exception as e:
                    fail_files.append(attachment.filename)
                    print(f"檔案儲存失敗: {file_name}, 錯誤: {str(e)}")

            # 轉義檔案名稱中的 Markdown 字符
            escaped_file_names_success = [discord.utils.escape_markdown(name) for name in success_files]
            file_names_str_success = ", ".join(escaped_file_names_success)  # 將檔案名稱列表轉為字串

            escaped_file_names_fail = [discord.utils.escape_markdown(name) for name in fail_files]
            file_names_str_fail = ", ".join(escaped_file_names_fail)  # 將檔案名稱列表轉為字串

            success_msg = f"成功上傳：{file_names_str_success}" if success_files else ""
            fail_msg = f"上傳失敗：{file_names_str_fail}" if fail_files else ""
            await message.delete()  # 刪除使用者上傳檔案的訊息
            await interaction.followup.send(f"{success_msg}\n{fail_msg}\n是否繼續上傳？", ephemeral=True, view=FileUploadView(self.reminder_data, self.files))
        except Exception as e:
            await interaction.followup.send(f"檔案上傳超時，請重試。\n{e}", ephemeral=True)

    @discord.ui.button(label="否", style=discord.ButtonStyle.danger)
    async def finish(self, interaction: discord.Interaction, button: discord.ui.Button):

        # 轉義檔案名稱中的 Markdown 字符
        escaped_file_names = [discord.utils.escape_markdown(name) for name in self.files]
        file_names_str = ", ".join(escaped_file_names)  # 將檔案名稱列表轉為字串

        ButtonDisabler.disable_and_stop(self, button)
        message_content = (
            f"表單輸入的資料：\n"
            f"標題：{self.reminder_data['Title']}\n"
            f"內容：{self.reminder_data['Content']}\n"
            f"第一次提醒時間：{self.reminder_data['First Reminder Time']}\n"
            f"重複次數：{self.reminder_data['Repeat Count']}\n"
            f"重複間隔：{self.reminder_data['Repeat Interval']} 小時\n"
            f"上傳的檔案：{file_names_str if file_names_str else 'None'}\n\n"
            f"提醒事項已完成設定並保存。\n請確認是否完全正確。"
        )
        confirm_view = ConfirmFinalView(self.reminder_data, self.files)
        await interaction.response.send_message(message_content, ephemeral=True, view=confirm_view)

class CancelUploadView(discord.ui.View):
    def __init__(self, reminder_data, files):
        super().__init__()
        self.reminder_data = reminder_data
        self.files = files

    @discord.ui.button(label="取消本次上傳", style=discord.ButtonStyle.secondary)
    async def cancel_upload(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        await interaction.response.send_message("是否繼續上傳？", ephemeral=True, view=FileUploadView(self.reminder_data, self.files))

class ConfirmFinalView(discord.ui.View):
    def __init__(self, reminder_data, files):
        super().__init__()
        self.reminder_data = reminder_data
        self.files = files
    
    def save_reminder_data(self, reminder_data):
        # 儲存檔案名稱欄位
        files = ', '.join(self.files) if self.files else "None"
        reminder_data["Files"] = files
        # 將提醒事項的內容換行更改為\n
        reminder_data["Content"] = reminder_data["Content"].replace("\n", "\\n")

        # 儲存提醒資料到CSV檔案
        with open(data_file, "a", newline="", encoding="utf-8-sig") as f:
            writer = csv.writer(f)
            writer.writerow(reminder_data.values())
            f.flush()
        
    @discord.ui.button(label="是", style=discord.ButtonStyle.success)
    async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        self.save_reminder_data(self.reminder_data)
        await interaction.response.send_message("提醒事項設定已完成！", ephemeral=True)

    @discord.ui.button(label="否", style=discord.ButtonStyle.danger)
    async def deny(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        view = ErrorSelectionView(self.reminder_data, self.files)  # 新增的按鈕選項視圖
        await interaction.response.send_message("哪部分有錯誤？", ephemeral=True, view=view)

class ErrorSelectionView(discord.ui.View):
    def __init__(self, reminder_data, files):
        super().__init__()
        self.reminder_data = reminder_data
        self.files = files

    @discord.ui.button(label="表單輸入錯誤", style=discord.ButtonStyle.primary)
    async def form_error(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        self.reminder_data.clear()  # 清除表單資料
        await interaction.response.send_modal(ReminderForm())  # 表單重開，使用同一 reminder_id 並保留檔案

    @discord.ui.button(label="檔案上傳錯誤", style=discord.ButtonStyle.primary)
    async def file_error(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        view = FileErrorHandlingView(self.reminder_data, self.files)
        await interaction.response.send_message("是否刪除之前所上傳的所有檔案並重新上傳？", ephemeral=True, view=view)

    @discord.ui.button(label="表單以及檔案皆錯誤", style=discord.ButtonStyle.danger)
    async def all_error(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        view = AllErrorHandlingView(self.reminder_data, self.files)
        await interaction.response.send_message("是否刪除之前的所有資料，並重新填寫？", ephemeral=True, view=view)

class FileErrorHandlingView(discord.ui.View):
    def __init__(self, reminder_data, files):
        super().__init__()
        self.reminder_data = reminder_data
        self.files = files

    @discord.ui.button(label="刪除並重新上傳", style=discord.ButtonStyle.danger)
    async def delete_and_reupload(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        # 檢查是否有檔案，若無檔案則不執行刪除操作
        if self.files:
            for file_path in self.files:
                os.remove(f"data/reminder_files/{self.reminder_data['ID']}/{file_path}")
            os.rmdir(f"data/reminder_files/{self.reminder_data['ID']}")
            await interaction.response.send_message("請重新上傳檔案。", ephemeral=True, view=FileUploadView(self.reminder_data))
        else:
            await interaction.response.send_message("沒有任何上傳的檔案\n您是否需要上傳相關檔案？", ephemeral=True, view=FileUploadView(self.reminder_data))

    @discord.ui.button(label="刪除並結束上傳", style=discord.ButtonStyle.danger)
    async def delete_and_finish(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        for file_path in self.files:
            os.remove(f"data/reminder_files/{self.reminder_data['ID']}/{file_path}")
        self.files.clear()
        
        # 轉義檔案名稱中的 Markdown 字符
        escaped_file_names = [discord.utils.escape_markdown(name) for name in self.files]
        file_names_str = ", ".join(escaped_file_names)  # 將檔案名稱列表轉為字串

        message_content = (
            f"表單輸入的資料：\n"
            f"標題：{self.reminder_data['Title']}\n"
            f"內容：{self.reminder_data['Content']}\n"
            f"第一次提醒時間：{self.reminder_data['First Reminder Time']}\n"
            f"重複次數：{self.reminder_data['Repeat Count']}\n"
            f"重複間隔：{self.reminder_data['Repeat Interval']} 小時\n"
            f"上傳的檔案：{file_names_str if file_names_str else 'None'}\n\n"
            f"提醒事項已完成設定並保存。\n請確認是否完全正確。"
        )
        confirm_view = ConfirmFinalView(self.reminder_data, self.files)
        await interaction.response.send_message(message_content, ephemeral=True, view=confirm_view)


class AllErrorHandlingView(discord.ui.View):
    def __init__(self, reminder_data, files):
        super().__init__()
        self.reminder_data = reminder_data
        self.files = files

    @discord.ui.button(label="刪除所有並重新填寫", style=discord.ButtonStyle.danger)
    async def delete_all_and_refill(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        # 檢查是否有檔案，若無則避免錯誤
        if self.files:
            for file_path in self.files:
                os.remove(f"data/reminder_files/{self.reminder_data['ID']}/{file_path}")
            os.rmdir(f"data/reminder_files/{self.reminder_data['ID']}")
        self.reminder_data.clear()
        await interaction.response.send_modal(ReminderForm())

    @discord.ui.button(label="刪除所有並結束", style=discord.ButtonStyle.secondary)
    async def delete_all_and_finish(self, interaction: discord.Interaction, button: discord.ui.Button):
        ButtonDisabler.disable_and_stop(self, button)
        # 檢查是否有檔案，若無則避免錯誤
        if self.files:
            for file_path in self.files:
                os.remove(f"data/reminder_files/{self.reminder_data['ID']}/{file_path}")
            os.rmdir(f"data/reminder_files/{self.reminder_data['ID']}")
        self.reminder_data.clear()
        await interaction.response.send_message("所有資料已刪除，提醒事項設定取消。", ephemeral=True)



class ReminderCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def reminder(self, ctx):
        await ctx.send("請填寫提醒事項表單。", view=ReminderForm())

async def setup(bot):
    await bot.add_cog(ReminderCog(bot))
