from typing import Iterable, Union, Tuple
from vector import *
from sys import path
from os.path import abspath, dirname

path.append(dirname(abspath("")))

from Scalar import Scalar


# the_3D 矩阵类
class Matrix3D:
    """三维矩阵类（3x3）"""

    def __init__(self, data: Iterable[Vector3D] = None) -> None:
        if data is None:
            # 当data为None时，使用基向量初始化单位矩阵
            data_list = [base_vector3D_i, base_vector3D_j, base_vector3D_k]
        else:
            data_list = list(data)
            if len(data_list) != 3 or not all(isinstance(v, Vector3D) for v in data_list):
                raise TypeError('data必须是包含三个Vector3D实例的可迭代对象')
        self.rows = data_list  # 存储三行向量

    @property
    def i(self) -> Vector3D:
        return self.rows[0]

    @property
    def j(self) -> Vector3D:
        return self.rows[1]

    @property
    def k(self) -> Vector3D:
        return self.rows[2]

    def det(self) -> Scalar:
        """计算矩阵行列式"""
        # 按第一行展开
        return (
                self.i.x * (self.j.y * self.k.z - self.j.z * self.k.y) -
                self.i.y * (self.j.x * self.k.z - self.j.z * self.k.x) +
                self.i.z * (self.j.x * self.k.y - self.j.y * self.k.x)
        )

    def __mul__(self, other: 'Matrix3D') -> 'Matrix3D':
        if not isinstance(other, Matrix3D):
            raise TypeError("只能与Matrix3D类型相乘")
        # 矩阵乘法：行×列
        row1 = Vector3D(
            self.i.dot(Vector3D(other.i.x, other.j.x, other.k.x)),
            self.i.dot(Vector3D(other.i.y, other.j.y, other.k.y)),
            self.i.dot(Vector3D(other.i.z, other.j.z, other.k.z))
        )
        row2 = Vector3D(
            self.j.dot(Vector3D(other.i.x, other.j.x, other.k.x)),
            self.j.dot(Vector3D(other.i.y, other.j.y, other.k.y)),
            self.j.dot(Vector3D(other.i.z, other.j.z, other.k.z))
        )
        row3 = Vector3D(
            self.k.dot(Vector3D(other.i.x, other.j.x, other.k.x)),
            self.k.dot(Vector3D(other.i.y, other.j.y, other.k.y)),
            self.k.dot(Vector3D(other.i.z, other.j.z, other.k.z))
        )
        return Matrix3D([row1, row2, row3])

    def __str__(self) -> str:
        return f"Matrix3D({self.i}, {self.j}, {self.k})"

    def __repr__(self) -> str:
        return f"Matrix3D(rows={self.rows!r})"

    def __eq__(self, other: Any) -> bool:
        if not isinstance(other, Matrix3D):
            return False
        return self.rows == other.rows

    def __ne__(self, other: Any) -> bool:
        return not self.__eq__(other)

    def transpose(self) -> 'Matrix3D':
        """矩阵转置"""
        return Matrix3D([
            Vector3D(self.i.x, self.j.x, self.k.x),
            Vector3D(self.i.y, self.j.y, self.k.y),
            Vector3D(self.i.z, self.j.z, self.k.z)
        ])

    def multiply_vector(self, vec: Vector3D) -> Vector3D:
        """矩阵与向量相乘"""
        if not isinstance(vec, Vector3D):
            raise TypeError("只能与Vector3D类型相乘")
        return Vector3D(
            self.i.x * vec.x + self.j.x * vec.y + self.k.x * vec.z,
            self.i.y * vec.x + self.j.y * vec.y + self.k.y * vec.z,
            self.i.z * vec.x + self.j.z * vec.y + self.k.z * vec.z
        )

    def __iter__(self):
        yield from self.rows


# the_3D 单位矩阵
base_Matrix3D = Matrix3D()


def create_matrix3D(rows: Union[Tuple[Vector3D, Vector3D, Vector3D], Tuple[Scalar, ...]]) -> Matrix3D:
    """创建三维矩阵的工厂函数"""
    if isinstance(rows[0], Vector3D) and isinstance(rows[1], Vector3D) and isinstance(rows[2], Vector3D):
        return Matrix3D(rows)
    elif len(rows) == 9 and all(isinstance(x, Scalar) for x in rows):
        return Matrix3D([
            Vector3D(rows[0], rows[1], rows[2]),
            Vector3D(rows[3], rows[4], rows[5]),
            Vector3D(rows[6], rows[7], rows[8])
        ])
    else:
        raise TypeError("输入必须是三个Vector3D或九个Scalar的元组")