import pandas as pd
import numpy as n
from datetime import datetime
import plotly.offline as pyo
import plotly.io as pio
import plotly.graph_objs as go
import os
from PyPDF2 import PdfMerger
from PyPDF2 import PdfReader, PdfWriter
from pydrive2.drive import GoogleDrive
from pydrive2.auth import GoogleAuth

import plotly.graph_objs as go
import datetime as dt

from database_manager import DatabaseManager
from models import create_stock_model, get_stock_class
from sqlalchemy import exists

pio.kaleido.scope.mathjax = None


def output_pdf(db, code, name):
    # 株価データ取得
    session = db.get_session()
    stock_model = create_stock_model(f"stock_{code}", db.Base)
    stock_datas = session.query(stock_model).all()
    dicts = [
        {k: v for k, v in stock_data.__dict__.items() if k != "_sa_instance_state"}
        for stock_data in stock_datas
    ]

    # 辞書をDataFrameに変換
    df = pd.DataFrame(dicts)

    # dateカラムをインデックスに設定
    df.set_index("date", inplace=True)

    # 2024.4.1から2024.7.31までのチャートを作成
    df.index = pd.to_datetime(df.index)
    df = df.tail(80)
    df.index = pd.to_datetime(df.index).strftime("%m-%d-%Y")

    # レイアウト設定
    layout = {
        "height": 900,
        "title": {"text": f"{code} {name}", "x": 0.5},
        "xaxis": {"rangeslider": {"visible": False}},
        "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": "RSI", "side": "right"},  # RSI
        "yaxis5": {"domain": [0.0, 0.095], "title": "RCI", "side": "right"},  # RCI
        "plot_bgcolor": "light blue",
    }

    # データの設定
    data = [
        go.Candlestick(
            yaxis="y1",
            x=df.index,
            open=df["open"],
            high=df["high"],
            low=df["low"],
            close=df["close"],
            name="",
        ),
        # 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"},
        ),
        # RSI
        go.Scatter(
            yaxis="y4",
            x=df.index,
            y=df["rsi14"],
            name="RSI14",
            line={"color": "magenta", "width": 1},
        ),
        go.Scatter(
            yaxis="y4",
            x=df.index,
            y=df["rsi28"],
            name="RSI28",
            line={"color": "green", "width": 1},
        ),
        # RCI
        go.Scatter(
            yaxis="y5",
            x=df.index,
            y=df["rci9"],
            name="RSI14",
            line={"color": "magenta", "width": 1},
        ),
        go.Scatter(
            yaxis="y5",
            x=df.index,
            y=df["rci26"],
            name="RSI28",
            line={"color": "green", "width": 1},
        ),
    ]

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

    # 日付表示
    fig.update_layout(
        {
            "xaxis": {
                "tickvals": df.index[::2],
                "ticktext": [
                    "{}-{}".format(x.split("-")[0], x.split("-")[1])
                    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)
    )

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

    print(f"Graph saved as {output_file}")
    return output_file


db_manager = DatabaseManager()
session = db_manager.get_session()
Stock = get_stock_class(db_manager.Base)


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

# stocksテーブル 全件取得
stocks = session.query(Stock).all()
for stock in stocks:
    file = output_pdf(db_manager, stock.code, stock.name)
    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])

# 保存ファイル名
merged_file = "merged_chart_{}.pdf".format(datetime.now().strftime("%Y_%m_%d"))

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


# 認証ファイルのパス
CREDENTIALS_FILE = "credentials.json"

# Googleドライブにアップロードするための認証設定
gauth = GoogleAuth()

# コマンドラインから認証を行う（最初の認証時にはブラウザでログインが必要）
gauth.CommandLineAuth()

# GoogleDriveのインスタンスを作成し、認証情報を使用してアクセス
drive = GoogleDrive(gauth)

# アップロード先のGoogle ドライブ フォルダIDを指定
folder_id = "1gt3jxfJBCL5TxUKgUrqkVQWQlyNCL5WF"

# Googleドライブにアップロードするファイルのメタデータを作成
f = drive.CreateFile(
    {
        "title": merged_file,
        "mimeType": "application/pdf",
        "parents": [{"kind": "drive#fileLink", "id": folder_id}],
    }
)

# アップロードするファイルをセット
f.SetContentFile(merged_file)

# Googleドライブにファイルをアップロード
f.Upload()

# ファイルを削除
os.remove(merged_file)
