from typing import List
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai_tools import SerperDevTool, ScrapeWebsiteTool
from pydantic import BaseModel, Field
import os

# Model options
llm_models = [
    "gemini/gemini-1.5-flash",
    "gemini/gemini-1.5-pro",
    "gemini/gemini-pro"
]
selected_model = llm_models[0]

def set_model(selected_model_name):
    global selected_model
    selected_model = selected_model_name

def configure_api_keys(gemini_api_key):
    if not gemini_api_key:
        raise ValueError("Gemini API key is required")
    os.environ['GEMINI_API_KEY'] = gemini_api_key

# Pydantic models for output validation
class MarketStrategy(BaseModel):
    """Market strategy model"""
    name: str = Field(..., description="Name of the market strategy")
    tatics: List[str] = Field(..., description="List of tactics to be used in the market strategy")
    channels: List[str] = Field(..., description="List of channels to be used in the market strategy")
    KPIs: List[str] = Field(..., description="List of KPIs to be used in the market strategy")

class CampaignIdea(BaseModel):
    """Campaign idea model"""
    name: str = Field(..., description="Name of the campaign idea")
    description: str = Field(..., description="Description of the campaign idea")
    audience: str = Field(..., description="Audience of the campaign idea")
    channel: str = Field(..., description="Channel of the campaign idea")

class Copy(BaseModel):
    """Copy model"""
    title: str = Field(..., description="Title of the copy")
    body: str = Field(..., description="Body of the copy")

@CrewBase
class MarketingPostsCrew:
    """MarketingPosts crew"""
    agents_config = 'config/MarketingPostGeneratorAgent/agents.yaml'
    tasks_config = 'config/MarketingPostGeneratorAgent/tasks.yaml'

    @agent
    def lead_market_analyst(self) -> Agent:
        return Agent(
            config=self.agents_config['lead_market_analyst'],
            tools=[SerperDevTool(), ScrapeWebsiteTool()],
            verbose=True,
            llm=selected_model
        )

    @agent
    def chief_marketing_strategist(self) -> Agent:
        return Agent(
            config=self.agents_config['chief_marketing_strategist'],
            tools=[SerperDevTool(), ScrapeWebsiteTool()],
            verbose=True,
            llm=selected_model
        )

    @agent
    def creative_content_creator(self) -> Agent:
        return Agent(
            config=self.agents_config['creative_content_creator'],
            verbose=True,
            llm=selected_model
        )

    @task
    def research_task(self) -> Task:
        return Task(
            config=self.tasks_config['research_task'],
            agent=self.lead_market_analyst()
        )

    @task
    def project_understanding_task(self) -> Task:
        return Task(
            config=self.tasks_config['project_understanding_task'],
            agent=self.chief_marketing_strategist()
        )

    @task
    def marketing_strategy_task(self) -> Task:
        return Task(
            config=self.tasks_config['marketing_strategy_task'],
            agent=self.chief_marketing_strategist(),
            # output_json=MarketStrategy
        )

    @task
    def campaign_idea_task(self) -> Task:
        return Task(
            config=self.tasks_config['campaign_idea_task'],
            agent=self.creative_content_creator(),
            # output_json=CampaignIdea
        )

    @task
    def copy_creation_task(self) -> Task:
        return Task(
            config=self.tasks_config['copy_creation_task'],
            agent=self.creative_content_creator(),
            context=[self.marketing_strategy_task(), self.campaign_idea_task()],
            output_file="post_generation.md"
        )

    @crew
    def crew(self) -> Crew:
        """Creates the MarketingPosts crew"""
        return Crew(
            agents=self.agents,  # Automatically created by the @agent decorator
            tasks=self.tasks,    # Automatically created by the @task decorator
            process=Process.sequential,
            verbose=True,
            output_log_file=True
        )

def run_crew_mpga(gemini_api_key, customer_domain, project_description):
    """
    Run the MarketingPosts crew using the provided Gemini API key and inputs.

    Args:
        gemini_api_key (str): The Gemini API key.
        customer_domain (str): The customer domain.
        project_description (str): The project description.

    Returns:
        A tuple (result, logs) from the crew kickoff.
    """
    try:
        configure_api_keys(gemini_api_key)
        crew_instance = MarketingPostsCrew().crew()
        inputs = {
            "customer_domain": customer_domain,
            "project_description": project_description
        }
        result = crew_instance.kickoff(inputs=inputs)
        with open("post_generation.md", "r", encoding='utf-8') as f:
            post_generation = f.read()
        with open("logs.txt", 'r', encoding='utf-8') as f:
            logs = f.read()
        with open("logs.txt", 'w', encoding='utf-8') as f:
            f.truncate(0)
        return post_generation, logs
    except Exception as e:
        return f"Error: {str(e)}", ""