import pandas as pd
import plotly.io as pio
import plotly.graph_objs as go
import os
from datetime import datetime
from typing import List
from PyPDF2 import PdfReader, PdfWriter
from database_manager import DatabaseManager
from models import get_stock_class
from technical_analysis import (
    get_dataframe,
    check_ma_golden_cross,
    check_macd_golden_cross,
    check_rci_golden_cross,
    check_rising_condition,
)

pio.kaleido.scope.mathjax = None


def output_pdf(name: str, code: str, suffix: str) -> str:
    """
    指定された銘柄の株価データを取得し、チャートを作成して PDF ファイルとして保存する。

    Args:
        name (str): 株式の銘柄名。
        code (str): 株式の銘柄コード。
        suffix (str): ファイル名の接尾辞。

    Returns:
        str: 作成された PDF ファイルのパス。
    """
    # 株価データ取得
    df = get_dataframe(code)
    df = df.tail(80)
    df.index = pd.to_datetime(df.index).strftime("%Y-%m-%d")

    # レイアウト設定
    layout = {
        "height": 900,
        "title": {"x": 0.5, "text": f"{name} {code}"},
        "xaxis": {"rangeslider": {"visible": False}, "type": "category"},
        "yaxis1": {
            "domain": [0.36, 1.0],
            "title": "価格（円）",
            "side": "left",
            "tickformat": ",",
        },
        "yaxis2": {"domain": [0.30, 0.36]},  # x
        "yaxis3": {"domain": [0.20, 0.295], "title": "MACD", "side": "right"},  # MACD
        "yaxis4": {"domain": [0.10, 0.195], "title": "RCI", "side": "right"},  # RCI
        "yaxis5": {
            "domain": [0.0, 0.095],
            "title": "Volume",
            "side": "right",
        },  # Volume
        "plot_bgcolor": "light blue",
    }

    # データの設定
    data = [
        go.Candlestick(
            yaxis="y1",
            x=df.index,
            open=df["open"],
            high=df["high"],
            low=df["low"],
            close=df["close"],
            increasing_line_color="red",
            decreasing_line_color="gray",
            name=code,
        ),
        # 5日移動平均線
        go.Scatter(
            yaxis="y1",
            x=df.index,
            y=df["ma5"],
            name="MA5",
            line={"color": "royalblue", "width": 1.2},
        ),
        # 25日移動平均線
        go.Scatter(
            yaxis="y1",
            x=df.index,
            y=df["ma25"],
            name="MA25",
            line={"color": "lightseagreen", "width": 1.2},
        ),
        # ボリンジャーバンド
        go.Scatter(
            yaxis="y1",
            x=df.index,
            y=df["upper2"],
            name="",
            line={"color": "lavender", "width": 0},
        ),
        go.Scatter(
            yaxis="y1",
            x=df.index,
            y=df["lower2"],
            name="BB",
            line={"color": "lavender", "width": 0},
            fill="tonexty",
            fillcolor="rgba(170,170,170,.2)",
        ),
        # MACD
        go.Scatter(
            yaxis="y3",
            x=df.index,
            y=df["macd"],
            name="macd",
            line={"color": "magenta", "width": 1},
        ),
        go.Scatter(
            yaxis="y3",
            x=df.index,
            y=df["macd_signal"],
            name="signal",
            line={"color": "green", "width": 1},
        ),
        go.Bar(
            yaxis="y3",
            x=df.index,
            y=df["hist"],
            name="histgram",
            marker={"color": "slategray"},
        ),
        # RCI
        go.Scatter(
            yaxis="y4",
            x=df.index,
            y=df["rci9"],
            name="RCI9",
            line={"color": "magenta", "width": 1},
        ),
        go.Scatter(
            yaxis="y4",
            x=df.index,
            y=df["rci26"],
            name="RCI26",
            line={"color": "green", "width": 1},
        ),
        # Volume
        go.Bar(
            yaxis="y5",
            x=df.index,
            y=df["volume"],
            name="Volume",
            marker=dict(color="slategray"),
        ),
    ]

    # Figure作成
    fig = go.Figure(data=data, layout=go.Layout(layout))

    # 日付表示
    fig.update_layout(
        {
            "xaxis": {
                "tickvals": df.index[::2],
                "ticktext": [
                    "{}-{}".format(x.split("-")[1], x.split("-")[2])
                    for x in df.index[::2]
                ],
            }
        }
    )

    # 画像保存先のフォルダ（必要なら作成）
    output_dir = "output"
    os.makedirs(output_dir, exist_ok=True)

    # 現在時刻とコードを使ってファイル名を作成し、PDFとして保存
    output_file = os.path.join(
        output_dir,
        "{}_{}_{}.pdf".format(datetime.now().strftime("%Y_%m_%d"), code, suffix),
    )

    pio.write_image(fig, output_file, format="pdf")
    return output_file


def merge_pdf(data: List[List[str]], suffix: str) -> str:
    """
    指定された銘柄リストをもとにPDFレポートを作成し、
    すべてのPDFを1つのファイルに結合して保存する。

    Args:
        data (List[List[str]]): 銘柄情報を格納したリスト（例: [["1234", "銘柄A"], ["5678", "銘柄B"]]）。
        suffix (str): 生成するファイル名に付加する文字列。

    Returns:
        str: 作成されたPDFファイルのパス。
    """

    # PDFファイル名を格納するリスト
    pdf_files = []

    # stocksテーブル 全件取得
    for code, name in data:
        file = output_pdf(code, name, suffix)
        pdf_files.append(file)

    # １つのPDFファイルにまとめる
    pdf_writer = PdfWriter()
    for pdf_file in pdf_files:
        pdf_reader = PdfReader(str(pdf_file), strict=False)
        for i in range(len(pdf_reader.pages)):
            pdf_writer.add_page(pdf_reader.pages[i])

    # 画像保存先のフォルダ（必要なら作成）
    output_dir = "output"
    os.makedirs(output_dir, exist_ok=True)

    # 保存ファイルのパス
    file_name = "{}_{}.pdf".format(datetime.now().strftime("%Y_%m_%d"), suffix)
    merged_file = os.path.join(output_dir, file_name)

    # 保存
    with open(merged_file, "wb") as f:
        pdf_writer.write(f)

    # ファイルを削除
    for pdf_file in pdf_files:
        os.remove(pdf_file)

    return merged_file


db_manager = DatabaseManager()
session = db_manager.get_session()

# stocksテーブル 全件取得
stock = get_stock_class(db_manager.Base)
stocks = session.query(stock).all()


# 各銘柄を格納するリスト
ma_list = []
macd_list = []
rci_list = []
rise_list = []

for stock in stocks:
    df = get_dataframe(stock.code)
    if check_ma_golden_cross(df):
        print(f"{stock.name} ({stock.code}) 移動平均線 ゴールデンクロス発生")
        ma_list.append([stock.name, stock.code])

    if check_macd_golden_cross(df):
        print(f"{stock.name} ({stock.code}) MACD ゴールデンクロス発生")
        macd_list.append([stock.name, stock.code])

    if check_rci_golden_cross(df):
        print(f"{stock.name} ({stock.code}) RCI ゴールデンクロス発生")
        rci_list.append([stock.name, stock.code])

    if check_rising_condition(df):
        print(f"{stock.name} ({stock.code}) もうすぐ上昇が始まります")
        rise_list.append([stock.name, stock.code])

# RCIのゴールデンクロスを確認
for data in rci_list:
    print(data[0], data[1])

if len(rci_list) > 0:
    pdf_file = merge_pdf(rci_list, "rci")
