"""
Special Chemistry & Post-Translational Modifications Module.

This module handles unique chemical events beyond standard amino acid chains,
such as the formation of chromophores or other covalent modifications that
are critical for the function of certain proteins.
"""

import logging
from typing import Optional

import biotite.structure as struc
import numpy as np

logger = logging.getLogger(__name__)

# EDUCATIONAL OVERVIEW - GFP Chromophore Maturation:
# --------------------------------------------------
# The Green Fluorescent Protein (GFP) from Aequorea victoria is a biological
# marvel. Its fluorescence is "autocatalytic" - it doesn't require any
# external cofactors, just molecular oxygen.
#
# Process of Chromophore Formation:
# 1. Folding: The protein folds into a 11-stranded beta-barrel.
# 2. Cyclization: The backbone of residues Ser65, Tyr66, and Gly67 undergoes
#    a nucleophilic attack (Gly67 N attacks Ser65 C=O), creating an
#    imidazolinone ring.
# 3. Dehydration: Loss of a water molecule.
# 4. Oxidation: Molecular oxygen (O2) oxidates the Ca-Cb bond of Tyr66,
#    extending the π-conjugation system.
#
# The result is a highly conjugated heterocyclic system buried deep within
# the protective "can" of the beta-barrel, shielding it from water quenching.
#
# This module provides the tools to detect and (eventually) simulate this
# covalent modification in synthetic structures.


def find_gfp_chromophore_motif(structure: struc.AtomArray) -> Optional[dict]:
    """
    Scans the structure for the Ser-Tyr-Gly motif that forms the GFP chromophore.

    The chromophore is formed by the cyclization of residues Ser-Tyr-Gly.
    This function identifies the indices of these three consecutive residues.

    Args:
        structure: Biotite AtomArray, must contain a single chain.

    Returns:
        A dictionary containing the residue IDs of S, Y, and G if the motif is found,
        otherwise None.
    """
    # Ensure we are working with a single protein chain
    if len(np.unique(structure.chain_id)) > 1:
        logger.warning("GFP chromophore search only supported for single chains.")
        return None

    res_ids, res_names = struc.get_residues(structure)

    for i in range(len(res_names) - 2):
        # Check for the S-Y-G sequence
        if res_names[i] == "SER" and res_names[i + 1] == "TYR" and res_names[i + 2] == "GLY":
            ser_res_id = res_ids[i]
            tyr_res_id = res_ids[i + 1]
            gly_res_id = res_ids[i + 2]

            logger.info(
                f"Found potential GFP chromophore motif: SER({ser_res_id})-TYR({tyr_res_id})-GLY({gly_res_id})"
            )
            return {
                "ser_res_id": ser_res_id,
                "tyr_res_id": tyr_res_id,
                "gly_res_id": gly_res_id,
            }

    return None


def form_gfp_chromophore(structure: struc.AtomArray, motif: dict) -> struc.AtomArray:
    """
    Forms the GFP chromophore by cyclizing the Ser-Tyr-Gly motif.

    NOTE: This is a placeholder and does not yet perform the actual chemical modification.

    Args:
        structure: The input AtomArray containing the SYG motif.
        motif: A dictionary identifying the residues to be modified.

    Returns:
        The modified AtomArray with the chromophore.
    """
    logger.warning("Chromophore formation is not yet implemented. Returning original structure.")
    return structure
