from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Form, Query, Body, Request from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session from typing import List, Optional, Dict, Any from datetime import datetime from app.core import get_db, get_current_user, get_current_active_user, get_current_admin_user from app.services import ( register_user, login_user, get_user_profile, update_user_profile, add_user_address, update_user_address, delete_user_address, create_category, update_category, delete_category, get_category_tree, create_product, update_product, delete_product, get_product_details, add_product_variant, update_product_variant, delete_product_variant, upload_product_image, update_product_image, delete_product_image, add_to_cart, update_cart_item, remove_from_cart, clear_cart, get_cart, create_order, get_order, update_order, cancel_order, create_review, update_review, delete_review, approve_review, get_product_reviews, create_page, update_page, delete_page, get_page_by_slug, log_event, get_analytics_report ) from app.schemas.user_schemas import ( UserCreate, UserUpdate, User, AddressCreate, AddressUpdate, Address, Token ) from app.schemas.catalog_schemas import ( CategoryCreate, CategoryUpdate, Category, ProductCreate, ProductUpdate, Product, ProductVariantCreate, ProductVariantUpdate, ProductVariant, ProductImageCreate, ProductImageUpdate, ProductImage ) from app.schemas.order_schemas import ( CartItemCreate, CartItemUpdate, CartItem, CartItemWithProduct, OrderCreate, OrderUpdate, Order, OrderWithDetails ) from app.schemas.review_schemas import ( ReviewCreate, ReviewUpdate, Review, ReviewWithUser ) from app.schemas.content_schemas import ( PageCreate, PageUpdate, Page, AnalyticsLogCreate, AnalyticsLog, AnalyticsReport ) from app.models.user_models import User as UserModel # Создаем основной роутер router = APIRouter() # Роутеры для аутентификации и пользователей auth_router = APIRouter(prefix="/auth", tags=["Аутентификация"]) @auth_router.post("/register", response_model=Dict[str, Any]) async def register(user: UserCreate, db: Session = Depends(get_db)): return register_user(db, user) @auth_router.post("/token", response_model=Token) async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)): result = login_user(db, form_data.username, form_data.password) return result user_router = APIRouter(prefix="/users", tags=["Пользователи"]) @user_router.get("/me", response_model=Dict[str, Any]) async def read_users_me(current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return get_user_profile(db, current_user.id) @user_router.put("/me", response_model=Dict[str, Any]) async def update_user_me(user_data: UserUpdate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return update_user_profile(db, current_user.id, user_data) @user_router.post("/me/addresses", response_model=Dict[str, Any]) async def create_user_address(address: AddressCreate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return add_user_address(db, current_user.id, address) @user_router.put("/me/addresses/{address_id}", response_model=Dict[str, Any]) async def update_user_address_endpoint(address_id: int, address: AddressUpdate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return update_user_address(db, current_user.id, address_id, address) @user_router.delete("/me/addresses/{address_id}", response_model=Dict[str, Any]) async def delete_user_address_endpoint(address_id: int, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return delete_user_address(db, current_user.id, address_id) @user_router.get("/{user_id}", response_model=Dict[str, Any]) async def read_user(user_id: int, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return get_user_profile(db, user_id) # Роутеры для каталога catalog_router = APIRouter(prefix="/catalog", tags=["Каталог"]) @catalog_router.post("/categories", response_model=Dict[str, Any]) async def create_category_endpoint(category: CategoryCreate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return create_category(db, category) @catalog_router.put("/categories/{category_id}", response_model=Dict[str, Any]) async def update_category_endpoint(category_id: int, category: CategoryUpdate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return update_category(db, category_id, category) @catalog_router.delete("/categories/{category_id}", response_model=Dict[str, Any]) async def delete_category_endpoint(category_id: int, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return delete_category(db, category_id) @catalog_router.get("/categories", response_model=List[Dict[str, Any]]) async def get_categories_tree(db: Session = Depends(get_db)): return get_category_tree(db) @catalog_router.post("/products", response_model=Dict[str, Any]) async def create_product_endpoint(product: ProductCreate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return create_product(db, product) @catalog_router.put("/products/{product_id}", response_model=Dict[str, Any]) async def update_product_endpoint(product_id: int, product: ProductUpdate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return update_product(db, product_id, product) @catalog_router.delete("/products/{product_id}", response_model=Dict[str, Any]) async def delete_product_endpoint(product_id: int, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return delete_product(db, product_id) @catalog_router.get("/products/{product_id}", response_model=Dict[str, Any]) async def get_product_details_endpoint(product_id: int, db: Session = Depends(get_db)): return get_product_details(db, product_id) @catalog_router.post("/products/{product_id}/variants", response_model=Dict[str, Any]) async def add_product_variant_endpoint(product_id: int, variant: ProductVariantCreate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): variant.product_id = product_id return add_product_variant(db, variant) @catalog_router.put("/variants/{variant_id}", response_model=Dict[str, Any]) async def update_product_variant_endpoint(variant_id: int, variant: ProductVariantUpdate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return update_product_variant(db, variant_id, variant) @catalog_router.delete("/variants/{variant_id}", response_model=Dict[str, Any]) async def delete_product_variant_endpoint(variant_id: int, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return delete_product_variant(db, variant_id) @catalog_router.post("/products/{product_id}/images", response_model=Dict[str, Any]) async def upload_product_image_endpoint( product_id: int, file: UploadFile = File(...), is_primary: bool = Form(False), current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db) ): return upload_product_image(db, product_id, file, is_primary) @catalog_router.put("/images/{image_id}", response_model=Dict[str, Any]) async def update_product_image_endpoint(image_id: int, image: ProductImageUpdate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return update_product_image(db, image_id, image) @catalog_router.delete("/images/{image_id}", response_model=Dict[str, Any]) async def delete_product_image_endpoint(image_id: int, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return delete_product_image(db, image_id) @catalog_router.get("/products", response_model=List[Product]) async def get_products( skip: int = 0, limit: int = 100, category_id: Optional[int] = None, search: Optional[str] = None, min_price: Optional[float] = None, max_price: Optional[float] = None, is_active: Optional[bool] = True, db: Session = Depends(get_db) ): from app.repositories.catalog_repo import get_products return get_products(db, skip, limit, category_id, search, min_price, max_price, is_active) # Роутеры для корзины и заказов cart_router = APIRouter(prefix="/cart", tags=["Корзина"]) @cart_router.post("/items", response_model=Dict[str, Any]) async def add_to_cart_endpoint(cart_item: CartItemCreate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return add_to_cart(db, current_user.id, cart_item) @cart_router.put("/items/{cart_item_id}", response_model=Dict[str, Any]) async def update_cart_item_endpoint(cart_item_id: int, cart_item: CartItemUpdate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return update_cart_item(db, current_user.id, cart_item_id, cart_item) @cart_router.delete("/items/{cart_item_id}", response_model=Dict[str, Any]) async def remove_from_cart_endpoint(cart_item_id: int, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return remove_from_cart(db, current_user.id, cart_item_id) @cart_router.delete("/clear", response_model=Dict[str, Any]) async def clear_cart_endpoint(current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return clear_cart(db, current_user.id) @cart_router.get("/", response_model=Dict[str, Any]) async def get_cart_endpoint(current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return get_cart(db, current_user.id) order_router = APIRouter(prefix="/orders", tags=["Заказы"]) @order_router.post("/", response_model=Dict[str, Any]) async def create_order_endpoint(order: OrderCreate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return create_order(db, current_user.id, order) @order_router.get("/{order_id}", response_model=Dict[str, Any]) async def get_order_endpoint(order_id: int, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return get_order(db, current_user.id, order_id, current_user.is_admin) @order_router.put("/{order_id}", response_model=Dict[str, Any]) async def update_order_endpoint(order_id: int, order: OrderUpdate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return update_order(db, current_user.id, order_id, order, current_user.is_admin) @order_router.post("/{order_id}/cancel", response_model=Dict[str, Any]) async def cancel_order_endpoint(order_id: int, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return cancel_order(db, current_user.id, order_id) @order_router.get("/", response_model=List[Order]) async def get_orders( skip: int = 0, limit: int = 100, status: Optional[str] = None, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db) ): if current_user.is_admin: from app.repositories.order_repo import get_all_orders return get_all_orders(db, skip, limit, status) else: from app.repositories.order_repo import get_user_orders return get_user_orders(db, current_user.id, skip, limit) # Роутеры для отзывов review_router = APIRouter(prefix="/reviews", tags=["Отзывы"]) @review_router.post("/", response_model=Dict[str, Any]) async def create_review_endpoint(review: ReviewCreate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return create_review(db, current_user.id, review) @review_router.put("/{review_id}", response_model=Dict[str, Any]) async def update_review_endpoint(review_id: int, review: ReviewUpdate, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return update_review(db, current_user.id, review_id, review, current_user.is_admin) @review_router.delete("/{review_id}", response_model=Dict[str, Any]) async def delete_review_endpoint(review_id: int, current_user: UserModel = Depends(get_current_active_user), db: Session = Depends(get_db)): return delete_review(db, current_user.id, review_id, current_user.is_admin) @review_router.post("/{review_id}/approve", response_model=Dict[str, Any]) async def approve_review_endpoint(review_id: int, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return approve_review(db, review_id) @review_router.get("/products/{product_id}", response_model=Dict[str, Any]) async def get_product_reviews_endpoint(product_id: int, skip: int = 0, limit: int = 10, db: Session = Depends(get_db)): return get_product_reviews(db, product_id, skip, limit) # Роутеры для информационных страниц content_router = APIRouter(prefix="/content", tags=["Контент"]) @content_router.post("/pages", response_model=Dict[str, Any]) async def create_page_endpoint(page: PageCreate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return create_page(db, page) @content_router.put("/pages/{page_id}", response_model=Dict[str, Any]) async def update_page_endpoint(page_id: int, page: PageUpdate, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return update_page(db, page_id, page) @content_router.delete("/pages/{page_id}", response_model=Dict[str, Any]) async def delete_page_endpoint(page_id: int, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db)): return delete_page(db, page_id) @content_router.get("/pages/{slug}", response_model=Dict[str, Any]) async def get_page_endpoint(slug: str, db: Session = Depends(get_db)): return get_page_by_slug(db, slug) @content_router.get("/pages", response_model=List[Page]) async def get_pages( skip: int = 0, limit: int = 100, published_only: bool = True, current_user: Optional[UserModel] = Depends(get_current_user), db: Session = Depends(get_db) ): # Если пользователь не админ, показываем только опубликованные страницы is_admin = current_user and current_user.is_admin from app.repositories.content_repo import get_pages return get_pages(db, skip, limit, published_only=(not is_admin) and published_only) # Роутеры для аналитики analytics_router = APIRouter(prefix="/analytics", tags=["Аналитика"]) @analytics_router.post("/events", response_model=Dict[str, Any]) async def log_event_endpoint(log: AnalyticsLogCreate, request: Request, db: Session = Depends(get_db)): # Добавляем IP-адрес и User-Agent, если они не указаны if not log.ip_address: log.ip_address = request.client.host if not log.user_agent: user_agent = request.headers.get("user-agent") if user_agent: log.user_agent = user_agent return log_event(db, log) @analytics_router.get("/reports", response_model=Dict[str, Any]) async def get_analytics_report_endpoint( period: str = "day", start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, current_user: UserModel = Depends(get_current_admin_user), db: Session = Depends(get_db) ): return get_analytics_report(db, period, start_date, end_date) # Включаем все роутеры в основной роутер router.include_router(auth_router) router.include_router(user_router) router.include_router(catalog_router) router.include_router(cart_router) router.include_router(order_router) router.include_router(review_router) router.include_router(content_router) router.include_router(analytics_router)