#!/usr/bin/env python3

import argparse
import asyncio
import json
import logging
import sqlite3
import time
from datetime import datetime, timezone
import httpx

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class ContentScheduler:
    """
    A content scheduler that reads posts from a JSON queue and posts them to social media.
    Currently supports Twitter and saves post history to a SQLite database.
    """

    def __init__(self, queue_file: str, db_file: str, twitter_bearer_token: str):
        """
        Initializes the ContentScheduler.

        Args:
            queue_file: Path to the JSON file containing the post queue.
            db_file: Path to the SQLite database file for storing post history.
            twitter_bearer_token: Bearer token for Twitter API access.
        """
        self.queue_file = queue_file
        self.db_file = db_file
        self.twitter_bearer_token = twitter_bearer_token
        self.client = httpx.Client()
        self.setup_db()

    def setup_db(self):
        """
        Sets up the SQLite database table for storing post history.
        """
        conn = sqlite3.connect(self.db_file)
        cursor = conn.cursor()
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS post_history (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
                platform TEXT NOT NULL,
                post_id TEXT,
                content TEXT NOT NULL,
                status_code INTEGER
            )
        """)
        conn.commit()
        conn.close()

    def load_queue(self) -> list[dict]:
        """
        Loads the post queue from the JSON file.

        Returns:
            A list of dictionaries, where each dictionary represents a post.
        """
        try:
            with open(self.queue_file, 'r') as f:
                queue = json.load(f)
            return queue
        except FileNotFoundError:
            logging.error(f"Queue file not found: {self.queue_file}")
            return []
        except json.JSONDecodeError:
            logging.error(f"Invalid JSON format in queue file: {self.queue_file}")
            return []

    def post_to_twitter(self, content: str) -> str | None:
        """
        Posts the given content to Twitter.

        Args:
            content: The content to post.

        Returns:
            The ID of the posted tweet if successful, otherwise None.
        """
        url = "https://api.twitter.com/2/tweets"
        headers = {
            "Authorization": f"Bearer {self.twitter_bearer_token}",
            "Content-Type": "application/json",
        }
        data = {"text": content}

        try:
            response = self.client.post(url, headers=headers, json=data)
            response.raise_for_status()  # Raise HTTPError for bad responses (4xx or 5xx)
            tweet_id = response.json().get("data", {}).get("id")
            return tweet_id
        except httpx.HTTPError as e:
            logging.error(f"Twitter API error: {e}")
            return None
        except Exception as e:
            logging.error(f"Error posting to Twitter: {e}")
            return None

    def save_post_history(self, platform: str, post_id: str, content: str, status_code: int):
        """
        Saves the post history to the SQLite database.

        Args:
            platform: The platform the post was sent to (e.g., "Twitter").
            post_id: The ID of the post on the platform.
            content: The content of the post.
            status_code: The HTTP status code of the post request.
        """
        conn = sqlite3.connect(self.db_file)
        cursor = conn.cursor()
        cursor.execute("""
            INSERT INTO post_history (platform, post_id, content, status_code)
            VALUES (?, ?, ?, ?)
        """, (platform, post_id, content, status_code))
        conn.commit()
        conn.close()

    async def process_queue(self):
        """
        Processes the post queue, posting each post at the appropriate time.
        """
        queue = self.load_queue()
        for post in queue:
            content = post["content"]
            scheduled_time = datetime.fromisoformat(post["scheduled_time"]).replace(tzinfo=timezone.utc)
            now = datetime.now(timezone.utc)

            if scheduled_time <= now:
                logging.info(f"Posting to Twitter: {content}")
                tweet_id = self.post_to_twitter(content)
                if tweet_id:
                    logging.info(f"Tweet posted successfully. Tweet ID: {tweet_id}")
                    self.save_post_history("Twitter", tweet_id, content, 200)
                else:
                    logging.error(f"Failed to post to Twitter: {content}")
                    self.save_post_history("Twitter", None, content, 500)
            else:
                delay = (scheduled_time - now).total_seconds()
                logging.info(f"Post scheduled for {scheduled_time}.  Waiting {delay:.2f} seconds.")
                await asyncio.sleep(delay)
                logging.info(f"Posting to Twitter: {content}")
                tweet_id = self.post_to_twitter(content)
                if tweet_id:
                    logging.info(f"Tweet posted successfully. Tweet ID: {tweet_id}")
                    self.save_post_history("Twitter", tweet_id, content, 200)
                else:
                    logging.error(f"Failed to post to Twitter: {content}")
                    self.save_post_history("Twitter", None, content, 500)

def main():
    """
    Main function to parse arguments and run the content scheduler.
    """
    parser = argparse.ArgumentParser(description="Content Scheduler for Social Media")
    parser.add_argument("--queue_file", required=True, help="Path to the JSON queue file.")
    parser.add_argument("--db_file", required=True, help="Path to the SQLite database file.")
    parser.add_argument("--twitter_bearer_token", required=True, help="Twitter API Bearer Token.")
    args = parser.parse_args()

    scheduler = ContentScheduler(args.queue_file, args.db_file, args.twitter_bearer_token)
    asyncio.run(scheduler.process_queue())

if __name__ == "__main__":
    main()