from typing import Optional, Union

from werkzeug.datastructures import FileStorage

from app.extensions import db
from app.models.base import Group
from app.models.cloud import CloudAccount
from app.models.mirrors import StaticOrigin


def create_static_origin(
        description: str,
        group_id: int,
        storage_cloud_account_id: int,
        source_cloud_account_id: int,
        source_project: str,
        auto_rotate: bool,
        matrix_homeserver: Optional[str],
        keanu_convene_path: Optional[str],
        keanu_convene_logo: Optional[FileStorage],
        keanu_convene_color: Optional[str],
        clean_insights_backend: Optional[Union[str, bool]],
        db_session_commit: bool = False,
) -> StaticOrigin:
    """
    Create a new static origin.

    :param description: The description of the new static origin.
    :param group_id: The ID for the origin group to add this new static origin to.
    :param storage_cloud_account_id: The ID for the cloud account to deploy this new static origin to.
    :param source_cloud_account_id: The ID for the cloud account used to interact with the web sources.
    :param source_project: The path for the source project, e.g. the GitLab project path.
    :param auto_rotate: Whether to automatically rotate this domain when it is detected to be blocked.
    :param matrix_homeserver: The domain name for the Matrix homeserver to proxy to.
    :param keanu_convene_path: The path to serve the Keanu Convene application from.
    :param clean_insights_backend: The domain name for the Clean Insights backend to proxy to.
    :param db_session_commit: Whether to add the new StaticOrigin to the database session and commit it.
    :returns: StaticOrigin -- the newly created StaticOrigin
    :raises: ValueError, sqlalchemy.exc.SQLAlchemyError
    """
    static_origin = StaticOrigin()
    if isinstance(group_id, int):
        group = Group.query.filter(Group.id == group_id).first()
        if group is None:
            raise ValueError("group_id must match an existing group")
        static_origin.group_id = group_id
    else:
        raise ValueError("group_id must be an int")
    if isinstance(storage_cloud_account_id, int):
        cloud_account = CloudAccount.query.filter(CloudAccount.id == storage_cloud_account_id).first()
        if cloud_account is None:
            raise ValueError("storage_cloud_account_id must match an existing provider")
        static_origin.storage_cloud_account_id = storage_cloud_account_id
    else:
        raise ValueError("storage_cloud_account_id must be an int")
    if isinstance(source_cloud_account_id, int):
        cloud_account = CloudAccount.query.filter(CloudAccount.id == source_cloud_account_id).first()
        if cloud_account is None:
            raise ValueError("source_cloud_account_id must match an existing provider")
        static_origin.source_cloud_account_id = source_cloud_account_id
    else:
        raise ValueError("source_cloud_account_id must be an int")
    static_origin.update(
        source_project,
        description,
        auto_rotate,
        matrix_homeserver,
        keanu_convene_path,
        keanu_convene_logo,
        keanu_convene_color,
        clean_insights_backend,
        False
    )
    if db_session_commit:
        db.session.add(static_origin)
        db.session.commit()
    return static_origin
